fix: Update default sink and source after setting it

This commit is contained in:
Fabio Lenherr / DashieTM 2023-12-09 13:39:38 +01:00
parent d3bc2edf88
commit 049a846c36
15 changed files with 425 additions and 258 deletions

View file

@ -808,14 +808,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/mio/mio-0.8.10.crate", "url": "https://static.crates.io/crates/mio/mio-0.8.9.crate",
"sha256": "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09", "sha256": "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0",
"dest": "cargo/vendor/mio-0.8.10" "dest": "cargo/vendor/mio-0.8.9"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09\", \"files\": {}}", "contents": "{\"package\": \"3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0\", \"files\": {}}",
"dest": "cargo/vendor/mio-0.8.10", "dest": "cargo/vendor/mio-0.8.9",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@ -873,14 +873,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/once_cell/once_cell-1.19.0.crate", "url": "https://static.crates.io/crates/once_cell/once_cell-1.18.0.crate",
"sha256": "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92", "sha256": "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d",
"dest": "cargo/vendor/once_cell-1.19.0" "dest": "cargo/vendor/once_cell-1.18.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92\", \"files\": {}}", "contents": "{\"package\": \"dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d\", \"files\": {}}",
"dest": "cargo/vendor/once_cell-1.19.0", "dest": "cargo/vendor/once_cell-1.18.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@ -964,14 +964,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-2.0.1.crate", "url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-2.0.0.crate",
"sha256": "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a", "sha256": "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8",
"dest": "cargo/vendor/proc-macro-crate-2.0.1" "dest": "cargo/vendor/proc-macro-crate-2.0.0"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a\", \"files\": {}}", "contents": "{\"package\": \"7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8\", \"files\": {}}",
"dest": "cargo/vendor/proc-macro-crate-2.0.1", "dest": "cargo/vendor/proc-macro-crate-2.0.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@ -1302,27 +1302,27 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/toml/toml-0.8.2.crate", "url": "https://static.crates.io/crates/toml/toml-0.8.8.crate",
"sha256": "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d", "sha256": "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35",
"dest": "cargo/vendor/toml-0.8.2" "dest": "cargo/vendor/toml-0.8.8"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d\", \"files\": {}}", "contents": "{\"package\": \"a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35\", \"files\": {}}",
"dest": "cargo/vendor/toml-0.8.2", "dest": "cargo/vendor/toml-0.8.8",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/toml_datetime/toml_datetime-0.6.3.crate", "url": "https://static.crates.io/crates/toml_datetime/toml_datetime-0.6.5.crate",
"sha256": "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b", "sha256": "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1",
"dest": "cargo/vendor/toml_datetime-0.6.3" "dest": "cargo/vendor/toml_datetime-0.6.5"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b\", \"files\": {}}", "contents": "{\"package\": \"3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1\", \"files\": {}}",
"dest": "cargo/vendor/toml_datetime-0.6.3", "dest": "cargo/vendor/toml_datetime-0.6.5",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@ -1341,14 +1341,27 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/toml_edit/toml_edit-0.20.2.crate", "url": "https://static.crates.io/crates/toml_edit/toml_edit-0.20.7.crate",
"sha256": "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338", "sha256": "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81",
"dest": "cargo/vendor/toml_edit-0.20.2" "dest": "cargo/vendor/toml_edit-0.20.7"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338\", \"files\": {}}", "contents": "{\"package\": \"70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81\", \"files\": {}}",
"dest": "cargo/vendor/toml_edit-0.20.2", "dest": "cargo/vendor/toml_edit-0.20.7",
"dest-filename": ".cargo-checksum.json"
},
{
"type": "archive",
"archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/toml_edit/toml_edit-0.21.0.crate",
"sha256": "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03",
"dest": "cargo/vendor/toml_edit-0.21.0"
},
{
"type": "inline",
"contents": "{\"package\": \"d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03\", \"files\": {}}",
"dest": "cargo/vendor/toml_edit-0.21.0",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {
@ -1562,14 +1575,14 @@
{ {
"type": "archive", "type": "archive",
"archive-type": "tar-gzip", "archive-type": "tar-gzip",
"url": "https://static.crates.io/crates/winnow/winnow-0.5.26.crate", "url": "https://static.crates.io/crates/winnow/winnow-0.5.19.crate",
"sha256": "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff", "sha256": "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b",
"dest": "cargo/vendor/winnow-0.5.26" "dest": "cargo/vendor/winnow-0.5.19"
}, },
{ {
"type": "inline", "type": "inline",
"contents": "{\"package\": \"b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff\", \"files\": {}}", "contents": "{\"package\": \"829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b\", \"files\": {}}",
"dest": "cargo/vendor/winnow-0.5.26", "dest": "cargo/vendor/winnow-0.5.19",
"dest-filename": ".cargo-checksum.json" "dest-filename": ".cargo-checksum.json"
}, },
{ {

View file

@ -23,6 +23,18 @@ use crate::components::{
output::sink_box::{start_output_box_listener, SinkBox}, output::sink_box::{start_output_box_listener, SinkBox},
}; };
#[derive(Default, PartialEq, Eq)]
pub enum Position {
Connectivity,
Wifi,
Bluetooth,
Audio,
AudioOutput,
AudioInput,
#[default]
Home,
}
#[derive(Default)] #[derive(Default)]
pub struct Listeners { pub struct Listeners {
pub wifi_disabled: AtomicBool, pub wifi_disabled: AtomicBool,
@ -405,11 +417,9 @@ pub fn start_audio_listener(
listeners.pulse_listener.store(true, Ordering::SeqCst); listeners.pulse_listener.store(true, Ordering::SeqCst);
println!("starting audio listener");
loop { loop {
let _ = conn.process(Duration::from_millis(1000)); let _ = conn.process(Duration::from_millis(1000));
if !listeners.pulse_listener.load(Ordering::SeqCst) { if !listeners.pulse_listener.load(Ordering::SeqCst) {
println!("stopping audio listener");
stop_dbus_audio_listener(conn); stop_dbus_audio_listener(conn);
break; break;
} }

View file

@ -40,7 +40,13 @@ unsafe impl Sync for SourceBox {}
impl SourceBox { impl SourceBox {
pub fn new() -> Self { pub fn new() -> Self {
Object::builder().build() let obj: Self = Object::builder().build();
{
let imp = obj.imp();
let mut model_index = imp.reset_model_index.write().unwrap();
*model_index = 0;
}
obj
} }
pub fn setup_callbacks(&self) { pub fn setup_callbacks(&self) {
@ -85,68 +91,70 @@ impl Default for SourceBox {
pub fn populate_sources(input_box: Arc<SourceBox>) { pub fn populate_sources(input_box: Arc<SourceBox>) {
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
let output_box_imp = input_box.imp();
let sources = get_sources(); let sources = get_sources();
{ {
let list = output_box_imp.reset_model_list.write().unwrap(); let input_box_imp = input_box.imp();
let mut map = output_box_imp.reset_source_map.write().unwrap(); let list = input_box_imp.reset_model_list.write().unwrap();
let mut model_index = output_box_imp.reset_model_index.write().unwrap(); let mut map = input_box_imp.reset_source_map.write().unwrap();
let mut model_index = input_box_imp.reset_model_index.write().unwrap();
input_box_imp
.reset_default_source
.replace(get_default_source());
for (i, source) in (0_u32..).zip(sources.iter()) { for (i, source) in (0_u32..).zip(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()));
*model_index += 1; *model_index += 1;
} }
} }
output_box_imp
.reset_default_source
.replace(get_default_source());
populate_outputstreams(input_box.clone()); populate_outputstreams(input_box.clone());
populate_cards(input_box.clone()); populate_cards(input_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 = input_box.clone(); let input_box_ref_slider = input_box.clone();
let output_box_ref_mute = input_box.clone(); let input_box_ref_toggle = input_box.clone();
let output_box_ref = input_box.clone(); let input_box_ref_mute = input_box.clone();
let input_box_ref = input_box.clone();
{ {
let output_box_imp = output_box_ref.imp(); let input_box_imp = input_box_ref.imp();
let default_sink = output_box_imp.reset_default_source.clone(); let default_sink = input_box_imp.reset_default_source.clone();
let source = default_sink.borrow(); let source = default_sink.borrow();
let volume = source.volume.first().unwrap_or(&0_u32); let volume = source.volume.first().unwrap_or(&0_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.reset_volume_percentage.set_text(&percentage); input_box_imp.reset_volume_percentage.set_text(&percentage);
output_box_imp.reset_volume_slider.set_value(*volume as f64); input_box_imp.reset_volume_slider.set_value(*volume as f64);
let mut list = output_box_imp.reset_source_list.write().unwrap(); let mut list = input_box_imp.reset_source_list.write().unwrap();
for stream in sources { for source in sources {
let index = source.index; let index = source.index;
let alias = source.alias.clone(); let alias = source.alias.clone();
let mut is_default = false; let mut is_default = false;
if output_box_imp.reset_default_source.borrow().name == stream.name { if input_box_imp.reset_default_source.borrow().name == source.name {
is_default = true; is_default = true;
} }
let source_entry = Arc::new(SourceEntry::new( let source_entry = Arc::new(SourceEntry::new(
is_default, is_default,
output_box_imp.reset_default_check_button.clone(), input_box_imp.reset_default_check_button.clone(),
stream, source,
input_box.clone(),
)); ));
let source_clone = source_entry.clone(); let source_clone = source_entry.clone();
let entry = Arc::new(ListEntry::new(&*source_entry)); let entry = Arc::new(ListEntry::new(&*source_entry));
entry.set_activatable(false); entry.set_activatable(false);
list.insert(index, (entry.clone(), source_clone, alias)); list.insert(index, (entry.clone(), source_clone, alias));
output_box_imp.reset_sources.append(&*entry); input_box_imp.reset_sources.append(&*entry);
} }
let list = output_box_imp.reset_model_list.read().unwrap(); let list = input_box_imp.reset_model_list.read().unwrap();
output_box_imp.reset_source_dropdown.set_model(Some(&*list)); input_box_imp.reset_source_dropdown.set_model(Some(&*list));
let map = output_box_imp.reset_source_map.read().unwrap(); let map = input_box_imp.reset_source_map.read().unwrap();
let name = output_box_imp.reset_default_source.borrow(); let name = input_box_imp.reset_default_source.borrow();
if let Some(index) = map.get(&name.alias) { if let Some(index) = map.get(&name.alias) {
output_box_imp.reset_source_dropdown.set_selected(index.1); input_box_imp.reset_source_dropdown.set_selected(index.1);
} }
output_box_imp input_box_imp.reset_source_dropdown.connect_selected_notify(
.reset_source_dropdown clone!(@weak input_box_imp => move |dropdown| {
.connect_selected_notify(clone!(@weak output_box_imp => move |dropdown| { let input_box = input_box_ref_toggle.clone();
let selected = dropdown.selected_item(); let selected = dropdown.selected_item();
if selected.is_none() { if selected.is_none() {
return; return;
@ -155,20 +163,27 @@ pub fn populate_sources(input_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.reset_source_map.read().unwrap(); let source = input_box_imp.reset_source_map.read().unwrap();
let source = source.get(&selected); let source = source.get(&selected);
if source.is_none() { if source.is_none() {
return; return;
} }
let sink = Arc::new(source.unwrap().2.clone()); let source = Arc::new(source.unwrap().2.clone());
set_default_source(sink); gio::spawn_blocking(move || {
})); let result = set_default_source(source);
if result.is_none(){
return;
}
refresh_default_source(result.unwrap(), input_box.clone(), false);
});
}),
);
} }
output_box_ref input_box_ref
.imp() .imp()
.reset_volume_slider .reset_volume_slider
.connect_change_value(move |_, _, value| { .connect_change_value(move |_, _, value| {
let imp = output_box_ref_slider.imp(); let imp = input_box_ref_slider.imp();
let fraction = (value / 655.36).round(); let fraction = (value / 655.36).round();
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.reset_volume_percentage.set_text(&percentage); imp.reset_volume_percentage.set_text(&percentage);
@ -188,27 +203,64 @@ pub fn populate_sources(input_box: Arc<SourceBox>) {
Propagation::Proceed Propagation::Proceed
}); });
output_box_ref input_box_ref
.imp() .imp()
.reset_source_mute .reset_source_mute
.connect_clicked(move |_| { .connect_clicked(move |_| {
let imp = output_box_ref_mute.imp(); let imp = input_box_ref_mute.imp();
let mut stream = imp.reset_default_source.borrow_mut(); let mut source = imp.reset_default_source.borrow_mut();
stream.muted = !stream.muted; source.muted = !source.muted;
if stream.muted { if source.muted {
imp.reset_source_mute imp.reset_source_mute
.set_icon_name("microphone-disabled-symbolic"); .set_icon_name("microphone-disabled-symbolic");
} else { } else {
imp.reset_source_mute imp.reset_source_mute
.set_icon_name("audio-input-microphone-symbolic"); .set_icon_name("audio-input-microphone-symbolic");
} }
toggle_source_mute(stream.index, stream.muted); toggle_source_mute(source.index, source.muted);
}); });
}); });
}); });
}); });
} }
pub fn refresh_default_source(new_source: Source, input_box: Arc<SourceBox>, 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 map = imp.reset_source_map.read().unwrap();
let entry = map.get(&new_source.alias);
if entry.is_none() {
return;
}
imp.reset_source_dropdown.set_selected(entry.unwrap().1);
}
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<SourceBox>) { pub fn populate_outputstreams(input_box: Arc<SourceBox>) {
let input_box_ref = input_box.clone(); let input_box_ref = input_box.clone();
@ -234,11 +286,11 @@ pub fn populate_outputstreams(input_box: Arc<SourceBox>) {
pub fn populate_cards(input_box: Arc<SourceBox>) { pub fn populate_cards(input_box: Arc<SourceBox>) {
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
let output_box_ref = input_box.clone(); let input_box_ref = input_box.clone();
let cards = get_cards(); let cards = get_cards();
glib::spawn_future(async move { glib::spawn_future(async move {
glib::idle_add_once(move || { glib::idle_add_once(move || {
let imp = output_box_ref.imp(); let imp = input_box_ref.imp();
for card in cards { for card in cards {
imp.reset_cards.add(&CardEntry::new(card)); imp.reset_cards.add(&CardEntry::new(card));
} }
@ -365,29 +417,30 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let source_box = source_added_box.clone(); let source_box = source_added_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 = source_box.clone(); let input_box = source_box.clone();
let output_box_imp = output_box.imp(); let input_box_imp = input_box.imp();
let mut list = output_box_imp.reset_source_list.write().unwrap(); let mut list = input_box_imp.reset_source_list.write().unwrap();
let source_index = ir.source.index; let source_index = ir.source.index;
let alias = ir.source.alias.clone(); let alias = ir.source.alias.clone();
let name = ir.source.name.clone(); let name = ir.source.name.clone();
let mut is_default = false; let mut is_default = false;
if output_box_imp.reset_default_source.borrow().name == ir.source.name { if input_box_imp.reset_default_source.borrow().name == ir.source.name {
is_default = true; is_default = true;
} }
let source_entry = Arc::new(SourceEntry::new( let source_entry = Arc::new(SourceEntry::new(
is_default, is_default,
output_box_imp.reset_default_check_button.clone(), input_box_imp.reset_default_check_button.clone(),
ir.source, ir.source,
input_box.clone(),
)); ));
let source_clone = source_entry.clone(); let source_clone = source_entry.clone();
let entry = Arc::new(ListEntry::new(&*source_entry)); let entry = Arc::new(ListEntry::new(&*source_entry));
entry.set_activatable(false); entry.set_activatable(false);
list.insert(source_index, (entry.clone(), source_clone, alias.clone())); list.insert(source_index, (entry.clone(), source_clone, alias.clone()));
output_box_imp.reset_sources.append(&*entry); input_box_imp.reset_sources.append(&*entry);
let mut map = output_box_imp.reset_source_map.write().unwrap(); let mut map = input_box_imp.reset_source_map.write().unwrap();
let mut index = output_box_imp.reset_model_index.write().unwrap(); let mut index = input_box_imp.reset_model_index.write().unwrap();
output_box_imp input_box_imp
.reset_model_list .reset_model_list
.write() .write()
.unwrap() .unwrap()
@ -407,29 +460,26 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let source_box = source_removed_box.clone(); let source_box = source_removed_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 = source_box.clone(); let input_box = source_box.clone();
let output_box_imp = output_box.imp(); let input_box_imp = input_box.imp();
let mut list = output_box_imp.reset_source_list.write().unwrap(); let mut list = input_box_imp.reset_source_list.write().unwrap();
let entry = list.get(&ir.index); let entry = list.remove(&ir.index);
if entry.is_none() { if entry.is_none() {
return; return;
} }
output_box_imp.reset_sources.remove(&*entry.unwrap().0); input_box_imp
list.remove(&ir.index); .reset_sources
let alias = list.remove(&ir.index); .remove(&*entry.clone().unwrap().0);
if alias.is_none() { let mut map = input_box_imp.reset_source_map.write().unwrap();
return; let entry_index = map.remove(&entry.unwrap().2);
}
let mut map = output_box_imp.reset_source_map.write().unwrap();
let entry_index = map.remove(&alias.unwrap().2);
if let Some(entry_index) = entry_index { if let Some(entry_index) = entry_index {
output_box_imp input_box_imp
.reset_model_list .reset_model_list
.write() .write()
.unwrap() .unwrap()
.remove(entry_index.1); .remove(entry_index.1);
} }
let mut index = output_box_imp.reset_model_index.write().unwrap(); let mut index = input_box_imp.reset_model_index.write().unwrap();
if *index != 0 { if *index != 0 {
*index -= 1; *index -= 1;
} }
@ -447,30 +497,31 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let default_source = get_default_source_name(); let default_source = get_default_source_name();
glib::spawn_future(async move { glib::spawn_future(async move {
glib::idle_add_once(move || { glib::idle_add_once(move || {
let output_box = source_box.clone(); let input_box = source_box.clone();
let output_box_imp = output_box.imp(); let input_box_imp = input_box.imp();
let is_default = ir.source.name == default_source; let is_default = ir.source.name == default_source;
let volume = ir.source.volume.first().unwrap_or(&0_u32); let volume = ir.source.volume.first().unwrap_or(&0_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() + "%";
let list = output_box_imp.reset_source_list.read().unwrap();
let list = input_box_imp.reset_source_list.read().unwrap();
let entry = list.get(&ir.source.index); let entry = list.get(&ir.source.index);
if entry.is_none() { if entry.is_none() {
return; return;
} }
let imp = entry.unwrap().1.imp(); let imp = entry.unwrap().1.imp();
if is_default { if is_default {
output_box_imp.reset_volume_percentage.set_text(&percentage); input_box_imp.reset_volume_percentage.set_text(&percentage);
output_box_imp.reset_volume_slider.set_value(*volume as f64); input_box_imp.reset_volume_slider.set_value(*volume as f64);
output_box_imp input_box_imp
.reset_default_source .reset_default_source
.replace(ir.source.clone()); .replace(ir.source.clone());
if ir.source.muted { if ir.source.muted {
output_box_imp input_box_imp
.reset_source_mute .reset_source_mute
.set_icon_name("microphone-disabled-symbolic"); .set_icon_name("microphone-disabled-symbolic");
} else { } else {
output_box_imp input_box_imp
.reset_source_mute .reset_source_mute
.set_icon_name("audio-input-microphone-symbolic"); .set_icon_name("audio-input-microphone-symbolic");
} }
@ -502,16 +553,15 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let source_box = output_stream_added_box.clone(); let source_box = output_stream_added_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 = source_box.clone(); let input_box = source_box.clone();
let output_box_imp = output_box.imp(); let input_box_imp = input_box.imp();
let mut list = output_box_imp.reset_output_stream_list.write().unwrap(); let mut list = input_box_imp.reset_output_stream_list.write().unwrap();
let index = ir.stream.index; let index = ir.stream.index;
let output_stream = Arc::new(OutputStreamEntry::new(output_box.clone(), ir.stream)); let output_stream = Arc::new(OutputStreamEntry::new(input_box.clone(), ir.stream));
let output_stream_clone = output_stream.clone();
let entry = Arc::new(ListEntry::new(&*output_stream)); let entry = Arc::new(ListEntry::new(&*output_stream));
entry.set_activatable(false); entry.set_activatable(false);
list.insert(index, (entry.clone(), output_stream_clone)); list.insert(index, (entry.clone(), output_stream.clone()));
output_box_imp.reset_output_streams.append(&*entry); input_box_imp.reset_output_streams.append(&*entry);
}); });
}); });
true true
@ -537,11 +587,11 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let source_box = output_stream_changed_box.clone(); let source_box = output_stream_changed_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 = source_box.clone(); let input_box = source_box.clone();
let output_box_imp = output_box.imp(); let input_box_imp = input_box.imp();
let entry: Arc<OutputStreamEntry>; let entry: Arc<OutputStreamEntry>;
{ {
let list = output_box_imp.reset_output_stream_list.read().unwrap(); let list = input_box_imp.reset_output_stream_list.read().unwrap();
let entry_opt = list.get(&ir.stream.index); let entry_opt = list.get(&ir.stream.index);
if entry_opt.is_none() { if entry_opt.is_none() {
return; return;
@ -563,7 +613,7 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.reset_volume_percentage.set_text(&percentage); imp.reset_volume_percentage.set_text(&percentage);
imp.reset_volume_slider.set_value(*volume as f64); imp.reset_volume_slider.set_value(*volume as f64);
let map = output_box_imp.reset_source_map.read().unwrap(); let map = input_box_imp.reset_source_map.read().unwrap();
if let Some(index) = map.get(&alias) { if let Some(index) = map.get(&alias) {
imp.reset_source_selection.set_selected(index.1); imp.reset_source_selection.set_selected(index.1);
} }
@ -583,14 +633,14 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc<SourceBox>) ->
let source_box = output_stream_removed_box.clone(); let source_box = output_stream_removed_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 = source_box.clone(); let input_box = source_box.clone();
let output_box_imp = output_box.imp(); let input_box_imp = input_box.imp();
let mut list = output_box_imp.reset_output_stream_list.write().unwrap(); let mut list = input_box_imp.reset_output_stream_list.write().unwrap();
let entry = list.remove(&ir.index); let entry = list.remove(&ir.index);
if entry.is_none() { if entry.is_none() {
return; return;
} }
output_box_imp input_box_imp
.reset_output_streams .reset_output_streams
.remove(&*entry.unwrap().0); .remove(&*entry.unwrap().0);
}); });

View file

@ -11,6 +11,7 @@ use glib::{clone, Propagation};
use gtk::{gio, CheckButton}; use gtk::{gio, CheckButton};
use re_set_lib::audio::audio_structures::Source; use re_set_lib::audio::audio_structures::Source;
use super::source_box::{refresh_default_source, SourceBox};
use super::source_entry_impl; use super::source_entry_impl;
glib::wrapper! { glib::wrapper! {
@ -23,26 +24,31 @@ unsafe impl Send for SourceEntry {}
unsafe impl Sync for SourceEntry {} unsafe impl Sync for SourceEntry {}
impl SourceEntry { 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>,
source: Source,
input_box: Arc<SourceBox>,
) -> 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
{ {
let imp = obj.imp(); let imp = obj.imp();
imp.reset_source_name imp.reset_source_name
.set_title(stream.alias.clone().as_str()); .set_title(source.alias.clone().as_str());
let name = Arc::new(stream.name.clone()); let name = Arc::new(source.name.clone());
let volume = stream.volume.first().unwrap_or(&0_u32); let volume = source.volume.first().unwrap_or(&0_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() + "%";
imp.reset_volume_percentage.set_text(&percentage); imp.reset_volume_percentage.set_text(&percentage);
imp.reset_volume_slider.set_value(*volume as f64); imp.reset_volume_slider.set_value(*volume as f64);
imp.stream.replace(stream); imp.source.replace(source);
imp.reset_volume_slider.connect_change_value( imp.reset_volume_slider.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();
let percentage = (fraction).to_string() + "%"; let percentage = (fraction).to_string() + "%";
imp.reset_volume_percentage.set_text(&percentage); imp.reset_volume_percentage.set_text(&percentage);
let source = imp.stream.borrow(); let source = imp.source.borrow();
let index = source.index; let index = source.index;
let channels = source.channels; let channels = source.channels;
{ {
@ -65,23 +71,30 @@ impl SourceEntry {
imp.reset_selected_source.set_active(false); imp.reset_selected_source.set_active(false);
} }
imp.reset_selected_source.connect_toggled(move |button| { imp.reset_selected_source.connect_toggled(move |button| {
let input_box = input_box.clone();
if button.is_active() { if button.is_active() {
set_default_source(name.clone()); let name = name.clone();
gio::spawn_blocking(move || {
let result = set_default_source(name);
if result.is_none() {
return;
}
refresh_default_source(result.unwrap(), input_box, true);
});
} }
}); });
imp.reset_source_mute imp.reset_source_mute
.connect_clicked(clone!(@weak imp => move |_| { .connect_clicked(clone!(@weak imp => move |_| {
let stream = imp.stream.clone(); let mut source = imp.source.borrow_mut();
let mut stream = stream.borrow_mut(); source.muted = !source.muted;
stream.muted = !stream.muted; if source.muted {
if stream.muted {
imp.reset_source_mute imp.reset_source_mute
.set_icon_name("microphone-disabled-symbolic"); .set_icon_name("microphone-disabled-symbolic");
} else { } else {
imp.reset_source_mute imp.reset_source_mute
.set_icon_name("audio-input-microphone-symbolic"); .set_icon_name("audio-input-microphone-symbolic");
} }
toggle_source_mute(stream.index, stream.muted); toggle_source_mute(source.index, source.muted);
})); }));
} }
obj obj
@ -127,22 +140,20 @@ pub fn toggle_source_mute(index: u32, muted: bool) -> bool {
true true
} }
pub fn set_default_source(name: Arc<String>) -> bool { pub fn set_default_source(name: Arc<String>) -> Option<Source> {
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.ReSetDaemon",
"org.Xetibo.ReSetDaemon", "/org/Xetibo/ReSetDaemon",
"/org/Xetibo/ReSetDaemon", Duration::from_millis(1000),
Duration::from_millis(1000), );
); let res: Result<(Source,), Error> = proxy.method_call(
let _: Result<(), Error> = "org.Xetibo.ReSetAudio",
proxy.method_call("org.Xetibo.ReSetAudio", "SetDefaultSink", (name.as_str(),)); "SetDefaultSource",
// if res.is_err() { (name.as_str(),),
// return; );
// } if res.is_err() {
// handle change return None;
}); }
true Some(res.unwrap().0)
} }
// TODO propagate error from dbus

View file

@ -25,7 +25,7 @@ pub struct SourceEntry {
pub reset_volume_percentage: TemplateChild<Label>, pub reset_volume_percentage: TemplateChild<Label>,
#[template_child] #[template_child]
pub reset_volume_meter: TemplateChild<ProgressBar>, pub reset_volume_meter: TemplateChild<ProgressBar>,
pub stream: Arc<RefCell<Source>>, pub source: Arc<RefCell<Source>>,
pub volume_time_stamp: RefCell<Option<SystemTime>>, pub volume_time_stamp: RefCell<Option<SystemTime>>,
} }

View file

View file

@ -4,3 +4,4 @@ pub mod sink_box;
pub mod sink_box_impl; pub mod sink_box_impl;
pub mod sink_entry; pub mod sink_entry;
pub mod sink_entry_impl; pub mod sink_entry_impl;
pub mod audio_box;

View file

@ -65,7 +65,6 @@ impl SinkBox {
self_imp self_imp
.reset_cards_row .reset_cards_row
.set_action_target_value(Some(&Variant::from("profileConfiguration"))); .set_action_target_value(Some(&Variant::from("profileConfiguration")));
self_imp.reset_cards_row.connect_action_name_notify(|_| {});
self_imp.reset_input_stream_button.set_activatable(true); self_imp.reset_input_stream_button.set_activatable(true);
self_imp self_imp
@ -92,12 +91,11 @@ impl Default for SinkBox {
pub fn populate_sinks(output_box: Arc<SinkBox>) { pub fn populate_sinks(output_box: Arc<SinkBox>) {
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
let output_box_ref = output_box.clone();
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.reset_sink_map.write().unwrap();
let list = output_box_imp.reset_model_list.write().unwrap(); let list = output_box_imp.reset_model_list.write().unwrap();
let mut map = output_box_imp.reset_sink_map.write().unwrap();
let mut model_index = output_box_imp.reset_model_index.write().unwrap(); let mut model_index = output_box_imp.reset_model_index.write().unwrap();
output_box_imp output_box_imp
.reset_default_sink .reset_default_sink
@ -112,8 +110,10 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
populate_cards(output_box.clone()); populate_cards(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_select = output_box.clone();
let output_box_ref_slider = output_box.clone(); let output_box_ref_slider = output_box.clone();
let output_box_ref_mute = 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 output_box_imp = output_box_ref.imp();
let default_sink = output_box_imp.reset_default_sink.clone(); let default_sink = output_box_imp.reset_default_sink.clone();
@ -136,6 +136,7 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
is_default, is_default,
output_box_imp.reset_default_check_button.clone(), output_box_imp.reset_default_check_button.clone(),
sink, sink,
output_box.clone(),
)); ));
let sink_clone = sink_entry.clone(); let sink_clone = sink_entry.clone();
let entry = Arc::new(ListEntry::new(&*sink_entry)); let entry = Arc::new(ListEntry::new(&*sink_entry));
@ -147,13 +148,12 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
output_box_imp.reset_sink_dropdown.set_model(Some(&*list)); output_box_imp.reset_sink_dropdown.set_model(Some(&*list));
let map = output_box_imp.reset_sink_map.read().unwrap(); let map = output_box_imp.reset_sink_map.read().unwrap();
let name = output_box_imp.reset_default_sink.borrow(); let name = output_box_imp.reset_default_sink.borrow();
let name = &name.alias; if let Some(index) = map.get(&name.alias) {
let index = map.get(name);
if let Some(index) = index {
output_box_imp.reset_sink_dropdown.set_selected(index.1); output_box_imp.reset_sink_dropdown.set_selected(index.1);
} }
output_box_imp.reset_sink_dropdown.connect_selected_notify( output_box_imp.reset_sink_dropdown.connect_selected_notify(
clone!(@weak output_box_imp => move |dropdown| { clone!(@weak output_box_imp => move |dropdown| {
let output_box_ref = output_box_ref_select.clone();
let selected = dropdown.selected_item(); let selected = dropdown.selected_item();
if selected.is_none() { if selected.is_none() {
return; return;
@ -167,8 +167,15 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
if sink.is_none() { if sink.is_none() {
return; return;
} }
let sink = Arc::new(sink.unwrap().2.clone()); let new_sink_name = Arc::new(sink.unwrap().2.clone());
set_default_sink(sink); gio::spawn_blocking(move || {
let result = set_default_sink(new_sink_name);
if result.is_none() {
return;
}
let new_sink = result.unwrap();
refresh_default_sink(new_sink, output_box_ref, false);
});
}), }),
); );
} }
@ -216,6 +223,43 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
}); });
} }
pub fn refresh_default_sink(new_sink: Sink, output_box: Arc<SinkBox>, 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 map = imp.reset_sink_map.read().unwrap();
let entry = map.get(&new_sink.alias);
if entry.is_none() {
return;
}
imp.reset_sink_dropdown.set_selected(entry.unwrap().1);
}
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<SinkBox>) { pub fn populate_inputstreams(output_box: Arc<SinkBox>) {
let output_box_ref = output_box.clone(); let output_box_ref = output_box.clone();
@ -283,6 +327,21 @@ fn get_sinks() -> Vec<Sink> {
res.unwrap().0 res.unwrap().0
} }
fn get_cards() -> Vec<Card> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let res: Result<(Vec<Card>,), Error> =
proxy.method_call("org.Xetibo.ReSetAudio", "ListCards", ());
if res.is_err() {
return Vec::new();
}
res.unwrap().0
}
fn get_default_sink_name() -> String { fn get_default_sink_name() -> String {
let conn = Connection::new_session().unwrap(); let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy( let proxy = conn.with_proxy(
@ -313,21 +372,6 @@ fn get_default_sink() -> Sink {
res.unwrap().0 res.unwrap().0
} }
fn get_cards() -> Vec<Card> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let res: Result<(Vec<Card>,), Error> =
proxy.method_call("org.Xetibo.ReSetAudio", "ListCards", ());
if res.is_err() {
return Vec::new();
}
res.unwrap().0
}
pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Connection { pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Connection {
let sink_added = SinkAdded::match_rule( let sink_added = SinkAdded::match_rule(
Some(&"org.Xetibo.ReSetDaemon".into()), Some(&"org.Xetibo.ReSetDaemon".into()),
@ -385,6 +429,7 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Co
is_default, is_default,
output_box_imp.reset_default_check_button.clone(), output_box_imp.reset_default_check_button.clone(),
ir.sink, ir.sink,
output_box.clone(),
)); ));
let sink_clone = sink_entry.clone(); let sink_clone = sink_entry.clone();
let entry = Arc::new(ListEntry::new(&*sink_entry)); let entry = Arc::new(ListEntry::new(&*sink_entry));
@ -416,17 +461,15 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Co
let output_box = sink_box.clone(); let output_box = sink_box.clone();
let output_box_imp = output_box.imp(); let output_box_imp = output_box.imp();
let mut list = output_box_imp.reset_sink_list.write().unwrap(); let mut list = output_box_imp.reset_sink_list.write().unwrap();
let entry = list.get(&ir.index); let entry = list.remove(&ir.index);
if entry.is_none() { if entry.is_none() {
return; return;
} }
output_box_imp.reset_sinks.remove(&*entry.unwrap().0); output_box_imp
let alias = list.remove(&ir.index); .reset_sinks
if alias.is_none() { .remove(&*entry.clone().unwrap().0);
return;
}
let mut map = output_box_imp.reset_sink_map.write().unwrap(); let mut map = output_box_imp.reset_sink_map.write().unwrap();
let entry_index = map.remove(&alias.unwrap().2); let entry_index = map.remove(&entry.unwrap().2);
if let Some(entry_index) = entry_index { if let Some(entry_index) = entry_index {
output_box_imp output_box_imp
.reset_model_list .reset_model_list
@ -529,8 +572,7 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Co
let alias: String; let alias: String;
{ {
let sink_list = imp.reset_sink_list.read().unwrap(); let sink_list = imp.reset_sink_list.read().unwrap();
let alias_opt = sink_list.get(&ir.stream.sink_index); if let Some(alias_opt) = sink_list.get(&ir.stream.sink_index) {
if let Some(alias_opt) = alias_opt {
alias = alias_opt.2.clone(); alias = alias_opt.2.clone();
} else { } else {
alias = String::from(""); alias = String::from("");
@ -566,8 +608,7 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Co
imp.reset_volume_percentage.set_text(&percentage); imp.reset_volume_percentage.set_text(&percentage);
imp.reset_volume_slider.set_value(*volume as f64); imp.reset_volume_slider.set_value(*volume as f64);
let map = output_box_imp.reset_sink_map.read().unwrap(); let map = output_box_imp.reset_sink_map.read().unwrap();
let index = map.get(&alias); if let Some(index) = map.get(&alias) {
if let Some(index) = index {
imp.reset_sink_selection.set_selected(index.1); imp.reset_sink_selection.set_selected(index.1);
} }
}); });
@ -586,14 +627,13 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc<SinkBox>) -> Co
let output_box = sink_box.clone(); let output_box = sink_box.clone();
let output_box_imp = output_box.imp(); let output_box_imp = output_box.imp();
let mut list = output_box_imp.reset_input_stream_list.write().unwrap(); let mut list = output_box_imp.reset_input_stream_list.write().unwrap();
let entry = list.get(&ir.index); let entry = list.remove(&ir.index);
if entry.is_none() { if entry.is_none() {
return; return;
} }
output_box_imp output_box_imp
.reset_input_streams .reset_input_streams
.remove(&*entry.unwrap().0); .remove(&*entry.unwrap().0);
list.remove(&ir.index);
}); });
}); });
true true

View file

@ -16,6 +16,8 @@ use super::sink_entry::SinkEntry;
type SinkEntryMap = Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<SinkEntry>, String)>>>; type SinkEntryMap = Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<SinkEntry>, String)>>>;
type InputStreamEntryMap = Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<InputStreamEntry>)>>>; type InputStreamEntryMap = Arc<RwLock<HashMap<u32, (Arc<ListEntry>, Arc<InputStreamEntry>)>>>;
// key is model name -> alias, first u32 is the index of the sink, the second the index in the model list and the third is
// the detailed name
type SinkMap = Arc<RwLock<HashMap<String, (u32, u32, String)>>>; type SinkMap = Arc<RwLock<HashMap<String, (u32, u32, String)>>>;
#[derive(Default, CompositeTemplate)] #[derive(Default, CompositeTemplate)]
@ -51,8 +53,6 @@ pub struct SinkBox {
pub reset_input_stream_list: InputStreamEntryMap, pub reset_input_stream_list: InputStreamEntryMap,
pub reset_model_list: Arc<RwLock<StringList>>, pub reset_model_list: Arc<RwLock<StringList>>,
pub reset_model_index: Arc<RwLock<u32>>, pub reset_model_index: Arc<RwLock<u32>>,
// first u32 is the index of the sink, the second the index in the model list and the third is
// the full name
pub reset_sink_map: SinkMap, pub reset_sink_map: SinkMap,
pub volume_time_stamp: RefCell<Option<SystemTime>>, pub volume_time_stamp: RefCell<Option<SystemTime>>,
} }

View file

@ -11,6 +11,7 @@ use glib::{clone, Propagation};
use gtk::{gio, CheckButton}; use gtk::{gio, CheckButton};
use re_set_lib::audio::audio_structures::Sink; use re_set_lib::audio::audio_structures::Sink;
use super::sink_box::{refresh_default_sink, SinkBox};
use super::sink_entry_impl; use super::sink_entry_impl;
glib::wrapper! { glib::wrapper! {
@ -23,7 +24,12 @@ unsafe impl Send for SinkEntry {}
unsafe impl Sync for SinkEntry {} unsafe impl Sync for SinkEntry {}
impl SinkEntry { impl SinkEntry {
pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Sink) -> Self { pub fn new(
is_default: bool,
check_group: Arc<CheckButton>,
stream: Sink,
output_box: Arc<SinkBox>,
) -> 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
{ {
@ -62,8 +68,16 @@ impl SinkEntry {
imp.reset_selected_sink.set_active(false); imp.reset_selected_sink.set_active(false);
} }
imp.reset_selected_sink.connect_toggled(move |button| { imp.reset_selected_sink.connect_toggled(move |button| {
let output_box_ref = output_box.clone();
if button.is_active() { if button.is_active() {
set_default_sink(name.clone()); let name = name.clone();
gio::spawn_blocking(move || {
let result = set_default_sink(name);
if result.is_none() {
return;
}
refresh_default_sink(result.unwrap(), output_box_ref, true);
});
} }
}); });
imp.reset_sink_mute imp.reset_sink_mute
@ -124,21 +138,17 @@ pub fn toggle_sink_mute(index: u32, muted: bool) -> bool {
true true
} }
pub fn set_default_sink(name: Arc<String>) { pub fn set_default_sink(name: Arc<String>) -> Option<Sink> {
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.ReSetDaemon",
"org.Xetibo.ReSetDaemon", "/org/Xetibo/ReSetDaemon",
"/org/Xetibo/ReSetDaemon", Duration::from_millis(1000),
Duration::from_millis(1000), );
); let res: Result<(Sink,), Error> =
let _: Result<(), Error> = proxy.method_call("org.Xetibo.ReSetAudio", "SetDefaultSink", (name.as_str(),));
proxy.method_call("org.Xetibo.ReSetAudio", "SetDefaultSink", (name.as_str(),)); if res.is_err() {
// if res.is_err() { return None;
// return; }
// } Some(res.unwrap().0)
// handle change
});
} }
// TODO propagate error from dbus

View file

@ -1,8 +1,10 @@
use gtk::prelude::FrameExt; use gtk::prelude::FrameExt;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use crate::components::base::setting_box::SettingBox; use crate::components::base::setting_box::SettingBox;
use crate::components::base::utils::{start_audio_listener, Listeners}; use crate::components::base::utils::{start_audio_listener, Listeners, Position};
use crate::components::bluetooth::bluetooth_box::{ use crate::components::bluetooth::bluetooth_box::{
populate_conntected_bluetooth_devices, start_bluetooth_listener, BluetoothBox, populate_conntected_bluetooth_devices, start_bluetooth_listener, BluetoothBox,
}; };
@ -14,9 +16,11 @@ use crate::components::wifi::wifi_box::{
use gtk::prelude::WidgetExt; use gtk::prelude::WidgetExt;
use gtk::{Align, FlowBox, FlowBoxChild, Frame}; use gtk::{Align, FlowBox, FlowBoxChild, Frame};
pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_audio_listener(); if handle_init(listeners.clone(), position, Position::Connectivity) {
return;
}
let wifi_box = WifiBox::new(listeners.clone()); let wifi_box = WifiBox::new(listeners.clone());
start_event_listener(listeners.clone(), wifi_box.clone()); start_event_listener(listeners.clone(), wifi_box.clone());
show_stored_connections(wifi_box.clone()); show_stored_connections(wifi_box.clone());
@ -24,7 +28,7 @@ pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc<Listeners>, FlowBox) =
let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box)); let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box));
let bluetooth_box = BluetoothBox::new(listeners.clone()); let bluetooth_box = BluetoothBox::new(listeners.clone());
populate_conntected_bluetooth_devices(bluetooth_box.clone()); populate_conntected_bluetooth_devices(bluetooth_box.clone());
start_bluetooth_listener(listeners.clone(), bluetooth_box.clone()); start_bluetooth_listener(listeners, bluetooth_box.clone());
let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box));
reset_main.remove_all(); reset_main.remove_all();
reset_main.insert(&wifi_frame, -1); reset_main.insert(&wifi_frame, -1);
@ -32,12 +36,13 @@ pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc<Listeners>, FlowBox) =
reset_main.set_max_children_per_line(2); reset_main.set_max_children_per_line(2);
}; };
pub const HANDLE_WIFI_CLICK: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_WIFI_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_audio_listener(); if handle_init(listeners.clone(), position, Position::Wifi) {
listeners.stop_bluetooth_listener(); return;
}
let wifi_box = WifiBox::new(listeners.clone()); let wifi_box = WifiBox::new(listeners.clone());
start_event_listener(listeners.clone(), wifi_box.clone()); start_event_listener(listeners, wifi_box.clone());
show_stored_connections(wifi_box.clone()); show_stored_connections(wifi_box.clone());
scan_for_wifi(wifi_box.clone()); scan_for_wifi(wifi_box.clone());
let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box)); let wifi_frame = wrap_in_flow_box_child(SettingBox::new(&*wifi_box));
@ -46,12 +51,13 @@ pub const HANDLE_WIFI_CLICK: fn(Arc<Listeners>, FlowBox) =
reset_main.set_max_children_per_line(1); reset_main.set_max_children_per_line(1);
}; };
pub const HANDLE_BLUETOOTH_CLICK: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_BLUETOOTH_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_network_listener(); if handle_init(listeners.clone(), position, Position::Bluetooth) {
listeners.stop_audio_listener(); return;
}
let bluetooth_box = BluetoothBox::new(listeners.clone()); let bluetooth_box = BluetoothBox::new(listeners.clone());
start_bluetooth_listener(listeners.clone(), bluetooth_box.clone()); start_bluetooth_listener(listeners, bluetooth_box.clone());
populate_conntected_bluetooth_devices(bluetooth_box.clone()); populate_conntected_bluetooth_devices(bluetooth_box.clone());
let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box)); let bluetooth_frame = wrap_in_flow_box_child(SettingBox::new(&*bluetooth_box));
reset_main.remove_all(); reset_main.remove_all();
@ -59,33 +65,35 @@ pub const HANDLE_BLUETOOTH_CLICK: fn(Arc<Listeners>, FlowBox) =
reset_main.set_max_children_per_line(1); reset_main.set_max_children_per_line(1);
}; };
pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_network_listener(); if handle_init(listeners.clone(), position, Position::Audio) {
listeners.stop_bluetooth_listener(); return;
}
let audio_output = Arc::new(SinkBox::new()); let audio_output = Arc::new(SinkBox::new());
let audio_input = Arc::new(SourceBox::new()); let audio_input = Arc::new(SourceBox::new());
start_audio_listener( start_audio_listener(
listeners.clone(), listeners,
Some(audio_output.clone()), Some(audio_output.clone()),
Some(audio_input.clone()), Some(audio_input.clone()),
); );
populate_sinks(audio_output.clone()); populate_sinks(audio_output.clone());
let audio_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_output));
populate_sources(audio_input.clone()); populate_sources(audio_input.clone());
let sink_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_output));
let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input)); let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input));
reset_main.remove_all(); reset_main.remove_all();
reset_main.insert(&audio_frame, -1); reset_main.insert(&sink_frame, -1);
reset_main.insert(&source_frame, -1); reset_main.insert(&source_frame, -1);
reset_main.set_max_children_per_line(2); reset_main.set_max_children_per_line(2);
}; };
pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_network_listener(); if handle_init(listeners.clone(), position, Position::AudioOutput) {
listeners.stop_bluetooth_listener(); return;
}
let audio_output = Arc::new(SinkBox::new()); let audio_output = Arc::new(SinkBox::new());
start_audio_listener(listeners.clone(), Some(audio_output.clone()), None); start_audio_listener(listeners, Some(audio_output.clone()), None);
populate_sinks(audio_output.clone()); populate_sinks(audio_output.clone());
let audio_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_output)); let audio_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_output));
reset_main.remove_all(); reset_main.remove_all();
@ -93,12 +101,13 @@ pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox) =
reset_main.set_max_children_per_line(1); reset_main.set_max_children_per_line(1);
}; };
pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_network_listener(); if handle_init(listeners.clone(), position, Position::AudioInput) {
listeners.stop_bluetooth_listener(); return;
}
let audio_input = Arc::new(SourceBox::new()); let audio_input = Arc::new(SourceBox::new());
start_audio_listener(listeners.clone(), None, Some(audio_input.clone())); start_audio_listener(listeners, None, Some(audio_input.clone()));
populate_sources(audio_input.clone()); populate_sources(audio_input.clone());
let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input)); let source_frame = wrap_in_flow_box_child(SettingBox::new(&*audio_input));
reset_main.remove_all(); reset_main.remove_all();
@ -106,11 +115,11 @@ pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox) =
reset_main.set_max_children_per_line(1); reset_main.set_max_children_per_line(1);
}; };
pub const HANDLE_HOME: fn(Arc<Listeners>, FlowBox) = pub const HANDLE_HOME: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>) =
|listeners: Arc<Listeners>, reset_main: FlowBox| { |listeners: Arc<Listeners>, reset_main: FlowBox, position: Rc<RefCell<Position>>| {
listeners.stop_network_listener(); if handle_init(listeners, position, Position::Home) {
listeners.stop_audio_listener(); return;
listeners.stop_bluetooth_listener(); }
reset_main.remove_all(); reset_main.remove_all();
}; };
@ -125,6 +134,24 @@ fn wrap_in_flow_box_child(widget: SettingBox) -> FlowBoxChild {
.build() .build()
} }
fn handle_init(
listeners: Arc<Listeners>,
position: Rc<RefCell<Position>>,
clicked_position: Position,
) -> bool {
{
let mut pos_borrow = position.borrow_mut();
if *pos_borrow == clicked_position {
return true;
}
*pos_borrow = clicked_position;
}
listeners.stop_network_listener();
listeners.stop_audio_listener();
listeners.stop_bluetooth_listener();
false
}
// for future implementations // for future implementations
// pub const HANDLE_VPN_CLICK: fn(Arc<Listeners>, FlowBox) = // pub const HANDLE_VPN_CLICK: fn(Arc<Listeners>, FlowBox) =
// |listeners: Arc<Listeners>, resetMain: FlowBox| { // |listeners: Arc<Listeners>, resetMain: FlowBox| {

View file

@ -45,7 +45,7 @@ impl ReSetWindow {
clone!(@ weak self_imp as flowbox => move |_, y| { clone!(@ weak self_imp as flowbox => move |_, y| {
let result = y.downcast_ref::<SidebarEntry>().unwrap(); let result = y.downcast_ref::<SidebarEntry>().unwrap();
let click_event = result.imp().on_click_event.borrow().on_click_event; let click_event = result.imp().on_click_event.borrow().on_click_event;
(click_event)(flowbox.listeners.clone(), flowbox.reset_main.get()); (click_event)(flowbox.listeners.clone(), flowbox.reset_main.get(), flowbox.position.clone());
}), }),
); );

View file

@ -1,4 +1,5 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use adw::glib::StaticTypeExt; use adw::glib::StaticTypeExt;
@ -9,7 +10,7 @@ use gtk::prelude::WidgetExt;
use gtk::subclass::prelude::*; use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate, FlowBox, ListBox, PopoverMenu, SearchEntry}; use gtk::{glib, Button, CompositeTemplate, FlowBox, ListBox, PopoverMenu, SearchEntry};
use crate::components::base::utils::Listeners; use crate::components::base::utils::{Listeners, Position};
use crate::components::wifi::wifi_box::WifiBox; use crate::components::wifi::wifi_box::WifiBox;
use crate::components::window::reset_window; use crate::components::window::reset_window;
use crate::components::window::sidebar_entry::SidebarEntry; use crate::components::window::sidebar_entry::SidebarEntry;
@ -41,6 +42,7 @@ pub struct ReSetWindow {
pub reset_shortcuts_button: TemplateChild<Button>, pub reset_shortcuts_button: TemplateChild<Button>,
pub sidebar_entries: RefCell<Vec<(SidebarEntry, Vec<SidebarEntry>)>>, pub sidebar_entries: RefCell<Vec<(SidebarEntry, Vec<SidebarEntry>)>>,
pub listeners: Arc<Listeners>, pub listeners: Arc<Listeners>,
pub position: Rc<RefCell<Position>>,
} }
unsafe impl Send for ReSetWindow {} unsafe impl Send for ReSetWindow {}
@ -83,7 +85,7 @@ impl WidgetImpl for ReSetWindow {
self.reset_main.set_margin_end(60); self.reset_main.set_margin_end(60);
} else { } else {
let div = (width - 540) / 2; let div = (width - 540) / 2;
if div > 1 { if div > 1 {
self.reset_main.set_margin_start(div); self.reset_main.set_margin_start(div);
self.reset_main.set_margin_end(div); self.reset_main.set_margin_end(div);
} else { } else {

View file

@ -1,6 +1,8 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use crate::components::base::utils::Listeners; use crate::components::base::utils::{Listeners, Position};
use crate::components::window::sidebar_entry_impl; use crate::components::window::sidebar_entry_impl;
use crate::components::window::sidebar_entry_impl::{Categories, SidebarAction}; use crate::components::window::sidebar_entry_impl::{Categories, SidebarAction};
use adw::subclass::prelude::ObjectSubclassIsExt; use adw::subclass::prelude::ObjectSubclassIsExt;
@ -20,7 +22,7 @@ impl SidebarEntry {
icon_name: &str, icon_name: &str,
category: Categories, category: Categories,
is_subcategory: bool, is_subcategory: bool,
click_event: fn(Arc<Listeners>, FlowBox), click_event: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>),
) -> Self { ) -> Self {
let entry: SidebarEntry = Object::builder().build(); let entry: SidebarEntry = Object::builder().build();
let entry_imp = entry.imp(); let entry_imp = entry.imp();

View file

@ -1,11 +1,12 @@
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use glib::subclass::InitializingObject; use glib::subclass::InitializingObject;
use gtk::subclass::prelude::*; use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, FlowBox, Image, Label, ListBoxRow}; use gtk::{glib, CompositeTemplate, FlowBox, Image, Label, ListBoxRow};
use crate::components::base::utils::Listeners; use crate::components::base::utils::{Listeners, Position};
use crate::components::window::handle_sidebar_click::HANDLE_HOME; use crate::components::window::handle_sidebar_click::HANDLE_HOME;
use crate::components::window::sidebar_entry; use crate::components::window::sidebar_entry;
@ -32,7 +33,7 @@ pub struct SidebarEntry {
} }
pub struct SidebarAction { pub struct SidebarAction {
pub on_click_event: fn(Arc<Listeners>, FlowBox), pub on_click_event: fn(Arc<Listeners>, FlowBox, Rc<RefCell<Position>>),
} }
impl Default for SidebarAction { impl Default for SidebarAction {