mirror of
https://github.com/Xetibo/ReSet.git
synced 2025-04-15 09:28:33 +02:00
commit
e0375b7b45
|
@ -1,4 +1,3 @@
|
|||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -8,10 +7,12 @@ use adw::prelude::{ButtonExt, RangeExt};
|
|||
use dbus::blocking::Connection;
|
||||
use dbus::Error;
|
||||
use glib::subclass::types::ObjectSubclassIsExt;
|
||||
use glib::{clone, Propagation};
|
||||
use glib::{clone, Cast, Propagation};
|
||||
use gtk::StringObject;
|
||||
use ReSet_Lib::audio::audio::OutputStream;
|
||||
|
||||
use super::outputStreamEntryImpl;
|
||||
use super::sourceBox::SourceBox;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct OutputStreamEntry(ObjectSubclass<outputStreamEntryImpl::OutputStreamEntry>)
|
||||
|
@ -20,12 +21,13 @@ glib::wrapper! {
|
|||
}
|
||||
|
||||
impl OutputStreamEntry {
|
||||
pub fn new(stream: OutputStream) -> Self {
|
||||
pub fn new(source_box: Arc<SourceBox>, stream: OutputStream) -> Self {
|
||||
let obj: Self = Object::builder().build();
|
||||
// TODO use event callback for progress bar -> this is the "im speaking" indicator
|
||||
// TODO map mute to callback
|
||||
// TODO map dropdown
|
||||
{
|
||||
let box_imp = source_box.imp();
|
||||
let imp = obj.imp();
|
||||
let name = stream.application_name.clone() + ": " + stream.name.as_str();
|
||||
imp.resetSourceName.set_text(name.as_str());
|
||||
|
@ -40,17 +42,75 @@ impl OutputStreamEntry {
|
|||
let fraction = (value / 655.36).round();
|
||||
let percentage = (fraction).to_string() + "%";
|
||||
imp.resetVolumePercentage.set_text(&percentage);
|
||||
let stream = imp.stream.borrow();
|
||||
let mut stream = imp.stream.try_borrow();
|
||||
while stream.is_err() {
|
||||
stream = imp.stream.try_borrow();
|
||||
}
|
||||
let stream = stream.unwrap();
|
||||
let index = stream.index;
|
||||
let channels = stream.channels;
|
||||
set_outputstream_volume(value, index, channels);
|
||||
Propagation::Proceed
|
||||
}),
|
||||
);
|
||||
{
|
||||
let mut list = box_imp.resetModelList.try_borrow();
|
||||
while list.is_err() {
|
||||
list = box_imp.resetModelList.try_borrow();
|
||||
}
|
||||
let list = list.unwrap();
|
||||
imp.resetSelectedSource.set_model(Some(&*list));
|
||||
let mut map = box_imp.resetSourceMap.try_borrow();
|
||||
while map.is_err() {
|
||||
map = box_imp.resetSourceMap.try_borrow();
|
||||
}
|
||||
let map = map.unwrap();
|
||||
let mut name = box_imp.resetDefaultSource.try_borrow();
|
||||
while name.is_err() {
|
||||
name = box_imp.resetDefaultSource.try_borrow();
|
||||
}
|
||||
let name = name.unwrap();
|
||||
let name = &name.alias;
|
||||
let index = map.get(name);
|
||||
if index.is_some() {
|
||||
imp.resetSelectedSource.set_selected(index.unwrap().1);
|
||||
}
|
||||
}
|
||||
imp.resetSelectedSource.connect_selected_notify(
|
||||
clone!(@weak imp, @weak box_imp => move |dropdown| {
|
||||
let selected = dropdown.selected_item();
|
||||
if selected.is_none() {
|
||||
return;
|
||||
}
|
||||
let selected = selected.unwrap();
|
||||
let selected = selected.downcast_ref::<StringObject>().unwrap();
|
||||
let selected = selected.string().to_string();
|
||||
let mut source = box_imp.resetSourceMap.try_borrow();
|
||||
while source.is_err() {
|
||||
source = box_imp.resetSourceMap.try_borrow();
|
||||
}
|
||||
let source = source.unwrap();
|
||||
let source = source.get(&selected);
|
||||
if source.is_none() {
|
||||
return;
|
||||
}
|
||||
let mut stream = imp.stream.try_borrow();
|
||||
while stream.is_err() {
|
||||
stream = imp.stream.try_borrow();
|
||||
}
|
||||
let stream = stream.unwrap();
|
||||
let source = source.unwrap().0;
|
||||
set_source_of_output_stream(stream.index, source);
|
||||
}),
|
||||
);
|
||||
imp.resetSourceMute
|
||||
.connect_clicked(clone!(@weak imp => move |_| {
|
||||
let stream = imp.stream.clone();
|
||||
let mut stream = stream.borrow_mut();
|
||||
let mut stream = stream.try_borrow_mut();
|
||||
while stream.is_err() {
|
||||
stream = imp.stream.try_borrow_mut();
|
||||
}
|
||||
let mut stream = stream.unwrap();
|
||||
stream.muted = !stream.muted;
|
||||
let muted = stream.muted;
|
||||
let index = stream.index;
|
||||
|
@ -100,3 +160,21 @@ fn toggle_output_stream_mute(index: u32, muted: bool) -> bool {
|
|||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
||||
fn set_source_of_output_stream(stream: u32, source: u32) -> bool {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(
|
||||
"org.xetibo.ReSet",
|
||||
"/org/xetibo/ReSet",
|
||||
Duration::from_millis(1000),
|
||||
);
|
||||
let res: Result<(bool,), Error> = proxy.method_call(
|
||||
"org.xetibo.ReSet",
|
||||
"SetSourceOfOutputStream",
|
||||
(stream, source),
|
||||
);
|
||||
if res.is_err() {
|
||||
return false;
|
||||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ use std::cell::RefCell;
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::components::input::outputStreamEntry;
|
||||
use ReSet_Lib::audio::audio::OutputStream;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{glib, Button, CompositeTemplate, Label, ProgressBar, Scale, DropDown};
|
||||
use gtk::{glib, Button, CompositeTemplate, DropDown, Label, ProgressBar, Scale};
|
||||
use ReSet_Lib::audio::audio::OutputStream;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Default, CompositeTemplate)]
|
||||
|
@ -23,6 +23,7 @@ pub struct OutputStreamEntry {
|
|||
#[template_child]
|
||||
pub resetVolumeMeter: TemplateChild<ProgressBar>,
|
||||
pub stream: Arc<RefCell<OutputStream>>,
|
||||
pub associatedSource: Arc<RefCell<(u32, String)>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
@ -45,4 +46,3 @@ impl BoxImpl for OutputStreamEntry {}
|
|||
impl ObjectImpl for OutputStreamEntry {}
|
||||
|
||||
impl WidgetImpl for OutputStreamEntry {}
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@ use adw::prelude::{BoxExt, ButtonExt, ListBoxRowExt, RangeExt};
|
|||
use dbus::blocking::Connection;
|
||||
use dbus::Error;
|
||||
use glib::subclass::prelude::ObjectSubclassIsExt;
|
||||
use glib::{Propagation, Variant};
|
||||
use gtk::gio;
|
||||
use glib::{clone, Cast, Propagation, Variant};
|
||||
use gtk::prelude::ActionableExt;
|
||||
use gtk::{gio, StringObject};
|
||||
use ReSet_Lib::audio::audio::{OutputStream, Source};
|
||||
|
||||
use super::outputStreamEntry::OutputStreamEntry;
|
||||
use super::sourceEntry::{toggle_source_mute, SourceEntry};
|
||||
use super::sourceEntry::{set_default_source, toggle_source_mute, SourceEntry};
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct SourceBox(ObjectSubclass<sourceBoxImpl::SourceBox>)
|
||||
|
@ -51,13 +51,23 @@ impl SourceBox {
|
|||
pub fn populate_sources(output_box: Arc<SourceBox>) {
|
||||
gio::spawn_blocking(move || {
|
||||
let output_box_imp = output_box.imp();
|
||||
let sinks = get_sources();
|
||||
let sources = get_sources();
|
||||
{
|
||||
let list = output_box_imp.resetModelList.borrow_mut();
|
||||
let mut map = output_box_imp.resetSourceMap.borrow_mut();
|
||||
let mut i: u32 = 0;
|
||||
for source in sources.iter() {
|
||||
list.append(&source.alias);
|
||||
map.insert(source.alias.clone(), (source.index, i, source.name.clone()));
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
output_box_imp
|
||||
.resetDefaultSource
|
||||
.replace(get_default_source());
|
||||
glib::spawn_future(async move {
|
||||
glib::idle_add_once(move || {
|
||||
// TODO handle default mapping
|
||||
// TODO handle events
|
||||
let output_box_ref_slider = output_box.clone();
|
||||
let output_box_ref_mute = output_box.clone();
|
||||
let output_box_ref = output_box.clone();
|
||||
|
@ -71,15 +81,49 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
|
|||
let percentage = (fraction).to_string() + "%";
|
||||
output_box_imp.resetVolumePercentage.set_text(&percentage);
|
||||
output_box_imp.resetVolumeSlider.set_value(*volume as f64);
|
||||
for stream in sinks {
|
||||
for stream in sources {
|
||||
let mut is_default = false;
|
||||
if output_box_imp.resetDefaultSource.borrow().name == stream.name {
|
||||
is_default = true;
|
||||
}
|
||||
let entry = ListEntry::new(&SourceEntry::new(is_default, output_box_imp.resetDefaultCheckButton.clone(), stream));
|
||||
let entry = ListEntry::new(&SourceEntry::new(
|
||||
is_default,
|
||||
output_box_imp.resetDefaultCheckButton.clone(),
|
||||
stream,
|
||||
));
|
||||
entry.set_activatable(false);
|
||||
output_box_imp.resetSources.append(&entry);
|
||||
}
|
||||
let list = output_box_imp.resetModelList.borrow();
|
||||
output_box_imp.resetSourceDropdown.set_model(Some(&*list));
|
||||
let map = output_box_imp.resetSourceMap.borrow();
|
||||
let name = output_box_imp.resetDefaultSource.borrow();
|
||||
let name = &name.alias;
|
||||
let index = map.get(name);
|
||||
if index.is_some() {
|
||||
output_box_imp
|
||||
.resetSourceDropdown
|
||||
.set_selected(index.unwrap().1);
|
||||
}
|
||||
output_box_imp.resetSourceDropdown.connect_selected_notify(
|
||||
clone!(@weak output_box_imp => move |dropdown| {
|
||||
let selected = dropdown.selected_item();
|
||||
if selected.is_none() {
|
||||
return;
|
||||
}
|
||||
let selected = selected.unwrap();
|
||||
let selected = selected.downcast_ref::<StringObject>().unwrap();
|
||||
let selected = selected.string().to_string();
|
||||
|
||||
let source = output_box_imp.resetSourceMap.borrow();
|
||||
let source = source.get(&selected);
|
||||
if source.is_none() {
|
||||
return;
|
||||
}
|
||||
let sink = Arc::new(source.unwrap().2.clone());
|
||||
set_default_source(sink);
|
||||
}),
|
||||
);
|
||||
}
|
||||
output_box_ref
|
||||
.imp()
|
||||
|
@ -121,7 +165,7 @@ pub fn populate_sources(output_box: Arc<SourceBox>) {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn populate_outputstreams(listeners: Arc<Listeners>, output_box: Arc<SourceBox>) {
|
||||
pub fn populate_outputstreams(_listeners: Arc<Listeners>, output_box: Arc<SourceBox>) {
|
||||
// TODO add listener
|
||||
let output_box_ref = output_box.clone();
|
||||
|
||||
|
@ -131,7 +175,7 @@ pub fn populate_outputstreams(listeners: Arc<Listeners>, output_box: Arc<SourceB
|
|||
glib::idle_add_once(move || {
|
||||
let output_box_imp = output_box_ref.imp();
|
||||
for stream in streams {
|
||||
let entry = ListEntry::new(&OutputStreamEntry::new(stream));
|
||||
let entry = ListEntry::new(&OutputStreamEntry::new(output_box.clone(), stream));
|
||||
entry.set_activatable(false);
|
||||
output_box_imp.resetOutputStreams.append(&entry);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::components::base::listEntry::ListEntry;
|
||||
use crate::components::input::sourceBox;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{glib, CompositeTemplate, DropDown, TemplateChild, CheckButton};
|
||||
use gtk::{glib, CheckButton, CompositeTemplate, DropDown, StringList, TemplateChild};
|
||||
use gtk::{prelude::*, Button, Label, ProgressBar, Scale};
|
||||
use ReSet_Lib::audio::audio::{OutputStream, Source};
|
||||
|
||||
|
@ -37,6 +38,9 @@ pub struct SourceBox {
|
|||
pub resetDefaultSource: Arc<RefCell<Source>>,
|
||||
pub resetSourceList: Arc<Mutex<Vec<Source>>>,
|
||||
pub resetOutputStreamList: Arc<Mutex<Vec<OutputStream>>>,
|
||||
pub resetModelList: Arc<RefCell<StringList>>,
|
||||
// first u32 is the index of the source, the second the index in the model list
|
||||
pub resetSourceMap: Arc<RefCell<HashMap<String, (u32, u32, String)>>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
@ -25,13 +24,10 @@ impl SourceEntry {
|
|||
pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Source) -> Self {
|
||||
let obj: Self = Object::builder().build();
|
||||
// TODO use event callback for progress bar -> this is the "im speaking" indicator
|
||||
// TODO map the slider to volume
|
||||
// TODO properly use volume fraction
|
||||
// TODO map mute to callback
|
||||
// TODO map dropdown
|
||||
// TODO handle events
|
||||
{
|
||||
let imp = obj.imp();
|
||||
imp.resetSourceName.set_text(stream.name.clone().as_str());
|
||||
imp.resetSourceName.set_text(stream.alias.clone().as_str());
|
||||
let name = Arc::new(stream.name.clone());
|
||||
let volume = stream.volume.first().unwrap_or_else(|| &(0 as u32));
|
||||
let fraction = (*volume as f64 / 655.36).round();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -8,11 +7,12 @@ use adw::prelude::{ButtonExt, RangeExt};
|
|||
use dbus::blocking::Connection;
|
||||
use dbus::Error;
|
||||
use glib::subclass::types::ObjectSubclassIsExt;
|
||||
use glib::subclass::ObjectImplRef;
|
||||
use glib::{clone, Propagation};
|
||||
use glib::{clone, Cast, Propagation};
|
||||
use gtk::StringObject;
|
||||
use ReSet_Lib::audio::audio::InputStream;
|
||||
|
||||
use super::inputStreamEntryImpl;
|
||||
use super::sinkBox::SinkBox;
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct InputStreamEntry(ObjectSubclass<inputStreamEntryImpl::InputStreamEntry>)
|
||||
|
@ -21,11 +21,12 @@ glib::wrapper! {
|
|||
}
|
||||
|
||||
impl InputStreamEntry {
|
||||
pub fn new(stream: InputStream) -> Self {
|
||||
pub fn new(sink_box: Arc<SinkBox>, stream: InputStream) -> Self {
|
||||
let obj: Self = Object::builder().build();
|
||||
// TODO use event callback for progress bar -> this is the "im speaking" indicator
|
||||
// TODO map dropdown
|
||||
// TODO handle events
|
||||
{
|
||||
let box_imp = sink_box.imp();
|
||||
let imp = obj.imp();
|
||||
if stream.muted {
|
||||
imp.resetSinkMute
|
||||
|
@ -42,22 +43,84 @@ impl InputStreamEntry {
|
|||
imp.resetVolumePercentage.set_text(&percentage);
|
||||
imp.resetVolumeSlider.set_value(*volume as f64);
|
||||
imp.stream.replace(stream);
|
||||
{
|
||||
let sink = box_imp.resetDefaultSink.borrow();
|
||||
imp.associatedSink.replace((sink.index, sink.name.clone()));
|
||||
}
|
||||
imp.resetVolumeSlider.connect_change_value(
|
||||
clone!(@weak imp => @default-return Propagation::Stop, move |_, _, value| {
|
||||
let fraction = (value / 655.36).round();
|
||||
let percentage = (fraction).to_string() + "%";
|
||||
imp.resetVolumePercentage.set_text(&percentage);
|
||||
let stream = imp.stream.borrow();
|
||||
let mut stream = imp.stream.try_borrow();
|
||||
while stream.is_err() {
|
||||
stream = imp.stream.try_borrow();
|
||||
}
|
||||
let stream = stream.unwrap();
|
||||
let index = stream.index;
|
||||
let channels = stream.channels;
|
||||
set_inputstream_volume(value, index, channels);
|
||||
Propagation::Proceed
|
||||
}),
|
||||
);
|
||||
{
|
||||
let mut list = box_imp.resetModelList.try_borrow();
|
||||
while list.is_err() {
|
||||
list = box_imp.resetModelList.try_borrow();
|
||||
}
|
||||
let list = list.unwrap();
|
||||
imp.resetSelectedSink.set_model(Some(&*list));
|
||||
let mut map = box_imp.resetSinkMap.try_borrow();
|
||||
while map.is_err() {
|
||||
map = box_imp.resetSinkMap.try_borrow();
|
||||
}
|
||||
let map = map.unwrap();
|
||||
let mut name = box_imp.resetDefaultSink.try_borrow();
|
||||
while name.is_err() {
|
||||
name = box_imp.resetDefaultSink.try_borrow();
|
||||
}
|
||||
let name = name.unwrap();
|
||||
let name = &name.alias;
|
||||
let index = map.get(name);
|
||||
if index.is_some() {
|
||||
imp.resetSelectedSink.set_selected(index.unwrap().1);
|
||||
}
|
||||
}
|
||||
imp.resetSelectedSink.connect_selected_notify(
|
||||
clone!(@weak imp, @weak box_imp => move |dropdown| {
|
||||
let selected = dropdown.selected_item();
|
||||
if selected.is_none() {
|
||||
return;
|
||||
}
|
||||
let selected = selected.unwrap();
|
||||
let selected = selected.downcast_ref::<StringObject>().unwrap();
|
||||
let selected = selected.string().to_string();
|
||||
let mut sink = box_imp.resetSinkMap.try_borrow();
|
||||
while sink.is_err() {
|
||||
sink = box_imp.resetSinkMap.try_borrow();
|
||||
}
|
||||
let sink = sink.unwrap();
|
||||
let sink = sink.get(&selected);
|
||||
if sink.is_none() {
|
||||
return;
|
||||
}
|
||||
let mut stream = imp.stream.try_borrow();
|
||||
while stream.is_err() {
|
||||
stream = imp.stream.try_borrow();
|
||||
}
|
||||
let stream = stream.unwrap();
|
||||
let sink = sink.unwrap().0;
|
||||
set_sink_of_input_stream(stream.index, sink);
|
||||
}),
|
||||
);
|
||||
imp.resetSinkMute
|
||||
.connect_clicked(clone!(@weak imp => move |_| {
|
||||
let stream = imp.stream.clone();
|
||||
let mut stream = stream.borrow_mut();
|
||||
let mut stream = stream.try_borrow_mut();
|
||||
while stream.is_err() {
|
||||
stream = imp.stream.try_borrow_mut();
|
||||
}
|
||||
let mut stream = stream.unwrap();
|
||||
stream.muted = !stream.muted;
|
||||
let muted = stream.muted;
|
||||
let index = stream.index;
|
||||
|
@ -107,3 +170,18 @@ fn toggle_input_stream_mute(index: u32, muted: bool) -> bool {
|
|||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
||||
fn set_sink_of_input_stream(stream: u32, sink: u32) -> bool {
|
||||
let conn = Connection::new_session().unwrap();
|
||||
let proxy = conn.with_proxy(
|
||||
"org.xetibo.ReSet",
|
||||
"/org/xetibo/ReSet",
|
||||
Duration::from_millis(1000),
|
||||
);
|
||||
let res: Result<(bool,), Error> =
|
||||
proxy.method_call("org.xetibo.ReSet", "SetSinkOfInputStream", (stream, sink));
|
||||
if res.is_err() {
|
||||
return false;
|
||||
}
|
||||
res.unwrap().0
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ pub struct InputStreamEntry {
|
|||
#[template_child]
|
||||
pub resetVolumeMeter: TemplateChild<ProgressBar>,
|
||||
pub stream: Arc<RefCell<InputStream>>,
|
||||
pub associatedSink: Arc<RefCell<(u32, String)>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
|
|
@ -10,14 +10,14 @@ use adw::{glib, prelude::ListBoxRowExt};
|
|||
use dbus::blocking::Connection;
|
||||
use dbus::Error;
|
||||
use glib::subclass::prelude::ObjectSubclassIsExt;
|
||||
use glib::{clone, Propagation, Variant};
|
||||
use gtk::gio;
|
||||
use glib::{clone, Cast, Propagation, Variant};
|
||||
use gtk::prelude::ActionableExt;
|
||||
use gtk::{gio, StringObject};
|
||||
use ReSet_Lib::audio::audio::{InputStream, Sink};
|
||||
|
||||
use super::inputStreamEntry::InputStreamEntry;
|
||||
use super::sinkBoxImpl;
|
||||
use super::sinkEntry::{toggle_sink_mute, SinkEntry};
|
||||
use super::sinkEntry::{set_default_sink, toggle_sink_mute, SinkEntry};
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct SinkBox(ObjectSubclass<sinkBoxImpl::SinkBox>)
|
||||
|
@ -51,20 +51,28 @@ impl SinkBox {
|
|||
pub fn populate_sinks(output_box: Arc<SinkBox>) {
|
||||
gio::spawn_blocking(move || {
|
||||
let output_box_ref = output_box.clone();
|
||||
let sinks = get_sinks();
|
||||
{
|
||||
let output_box_imp = output_box.imp();
|
||||
output_box_imp.resetDefaultSink.replace(get_default_sink());
|
||||
let list = output_box_imp.resetModelList.borrow_mut();
|
||||
let mut map = output_box_imp.resetSinkMap.borrow_mut();
|
||||
let mut i: u32 = 0;
|
||||
for sink in sinks.iter() {
|
||||
dbg!(sink.clone());
|
||||
list.append(&sink.alias);
|
||||
map.insert(sink.alias.clone(), (sink.index, i, sink.name.clone()));
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
let sinks = get_sinks();
|
||||
glib::spawn_future(async move {
|
||||
glib::idle_add_once(move || {
|
||||
// TODO handle default mapping
|
||||
let output_box_ref_slider = output_box.clone();
|
||||
let output_box_ref_mute = output_box.clone();
|
||||
{
|
||||
let output_box_imp = output_box_ref.imp();
|
||||
let default_sink = output_box_imp.resetDefaultSink.clone(); // Clone outside closure
|
||||
let sink = default_sink.borrow(); //
|
||||
let default_sink = output_box_imp.resetDefaultSink.clone();
|
||||
let sink = default_sink.borrow();
|
||||
|
||||
let volume = sink.volume.first().unwrap_or_else(|| &(0 as u32));
|
||||
let fraction = (*volume as f64 / 655.36).round();
|
||||
|
@ -72,15 +80,48 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
|
|||
output_box_imp.resetVolumePercentage.set_text(&percentage);
|
||||
output_box_imp.resetVolumeSlider.set_value(*volume as f64);
|
||||
for stream in sinks {
|
||||
// TODO create sink handler -> currently only allows input streams
|
||||
let mut is_default = false;
|
||||
if output_box_imp.resetDefaultSink.borrow().name == stream.name {
|
||||
is_default = true;
|
||||
}
|
||||
let entry = ListEntry::new(&SinkEntry::new(is_default, output_box_imp.resetDefaultCheckButton.clone(), stream));
|
||||
let entry = ListEntry::new(&SinkEntry::new(
|
||||
is_default,
|
||||
output_box_imp.resetDefaultCheckButton.clone(),
|
||||
stream,
|
||||
));
|
||||
entry.set_activatable(false);
|
||||
output_box_imp.resetSinks.append(&entry);
|
||||
}
|
||||
let list = output_box_imp.resetModelList.borrow();
|
||||
output_box_imp.resetSinkDropdown.set_model(Some(&*list));
|
||||
let map = output_box_imp.resetSinkMap.borrow();
|
||||
let name = output_box_imp.resetDefaultSink.borrow();
|
||||
let name = &name.alias;
|
||||
let index = map.get(name);
|
||||
if index.is_some() {
|
||||
output_box_imp
|
||||
.resetSinkDropdown
|
||||
.set_selected(index.unwrap().1);
|
||||
}
|
||||
output_box_imp.resetSinkDropdown.connect_selected_notify(
|
||||
clone!(@weak output_box_imp => move |dropdown| {
|
||||
let selected = dropdown.selected_item();
|
||||
if selected.is_none() {
|
||||
return;
|
||||
}
|
||||
let selected = selected.unwrap();
|
||||
let selected = selected.downcast_ref::<StringObject>().unwrap();
|
||||
let selected = selected.string().to_string();
|
||||
|
||||
let sink = output_box_imp.resetSinkMap.borrow();
|
||||
let sink = sink.get(&selected);
|
||||
if sink.is_none() {
|
||||
return;
|
||||
}
|
||||
let sink = Arc::new(sink.unwrap().2.clone());
|
||||
set_default_sink(sink);
|
||||
}),
|
||||
);
|
||||
}
|
||||
output_box_ref
|
||||
.imp()
|
||||
|
@ -121,13 +162,9 @@ pub fn populate_sinks(output_box: Arc<SinkBox>) {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn populate_inputstreams(listeners: Arc<Listeners>, output_box: Arc<SinkBox>) {
|
||||
pub fn populate_inputstreams(_listeners: Arc<Listeners>, output_box: Arc<SinkBox>) {
|
||||
// TODO add listener
|
||||
let output_box_ref = output_box.clone();
|
||||
// let output_box_ref_listener = output_box.clone();
|
||||
let output_box_imp = output_box.imp();
|
||||
// let sources = output_box_imp.resetSinks.clone();
|
||||
// let output_streams = output_box_imp.resetInputStreams.clone();
|
||||
|
||||
gio::spawn_blocking(move || {
|
||||
let streams = get_input_streams();
|
||||
|
@ -135,7 +172,7 @@ pub fn populate_inputstreams(listeners: Arc<Listeners>, output_box: Arc<SinkBox>
|
|||
glib::idle_add_once(move || {
|
||||
let output_box_imp = output_box_ref.imp();
|
||||
for stream in streams {
|
||||
let entry = ListEntry::new(&InputStreamEntry::new(stream));
|
||||
let entry = ListEntry::new(&InputStreamEntry::new(output_box.clone(), stream));
|
||||
entry.set_activatable(false);
|
||||
output_box_imp.resetInputStreams.append(&entry);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::components::base::listEntry::ListEntry;
|
||||
use crate::components::output::inputStreamEntry::InputStreamEntry;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{glib, Box, Button, CompositeTemplate, DropDown, Label, TemplateChild, CheckButton};
|
||||
use gtk::{
|
||||
glib, Box, Button, CheckButton, CompositeTemplate, DropDown, Label, StringList, TemplateChild,
|
||||
};
|
||||
use gtk::{prelude::*, ProgressBar, Scale};
|
||||
use ReSet_Lib::audio::audio::{InputStream, Sink};
|
||||
|
||||
|
@ -18,7 +21,7 @@ pub struct SinkBox {
|
|||
#[template_child]
|
||||
pub resetSinksRow: TemplateChild<ListEntry>,
|
||||
#[template_child]
|
||||
pub resetInputDevice: TemplateChild<DropDown>,
|
||||
pub resetSinkDropdown: TemplateChild<DropDown>,
|
||||
#[template_child]
|
||||
pub resetSinkMute: TemplateChild<Button>,
|
||||
#[template_child]
|
||||
|
@ -37,6 +40,9 @@ pub struct SinkBox {
|
|||
pub resetDefaultSink: Arc<RefCell<Sink>>,
|
||||
pub resetSinkList: Arc<Mutex<Vec<Sink>>>,
|
||||
pub resetInputStreamList: Arc<Mutex<Vec<InputStream>>>,
|
||||
pub resetModelList: Arc<RefCell<StringList>>,
|
||||
// first u32 is the index of the sink, the second the index in the model list
|
||||
pub resetSinkMap: Arc<RefCell<HashMap<String, (u32, u32, String)>>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
|
|
@ -24,10 +24,10 @@ impl SinkEntry {
|
|||
pub fn new(is_default: bool, check_group: Arc<CheckButton>, stream: Sink) -> Self {
|
||||
let obj: Self = Object::builder().build();
|
||||
// TODO use event callback for progress bar -> this is the "im speaking" indicator
|
||||
// TODO map dropdown
|
||||
// TODO handle events
|
||||
{
|
||||
let imp = obj.imp();
|
||||
imp.resetSinkName.set_text(stream.name.clone().as_str());
|
||||
imp.resetSinkName.set_text(stream.alias.clone().as_str());
|
||||
let name = Arc::new(stream.name.clone());
|
||||
let volume = stream.volume.first().unwrap_or_else(|| &(0 as u32));
|
||||
let fraction = (*volume as f64 / 655.36).round();
|
||||
|
@ -49,7 +49,6 @@ impl SinkEntry {
|
|||
}),
|
||||
);
|
||||
imp.resetSelectedSink.set_group(Some(&*check_group));
|
||||
// check_group.set_group(Some(&*imp.resetSelectedSink));
|
||||
if is_default {
|
||||
imp.resetSelectedSink.set_active(true);
|
||||
} else {
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||
|
||||
use crate::components::output::sinkEntry;
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::{glib, Button, CompositeTemplate, DropDown, Label, ProgressBar, Scale, CheckButton};
|
||||
use gtk::{glib, Button, CompositeTemplate, Label, ProgressBar, Scale, CheckButton};
|
||||
use ReSet_Lib::audio::audio::Sink;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown" id="resetInputDevice">
|
||||
<object class="GtkDropDown" id="resetSinkDropdown">
|
||||
<property name="halign">end</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="valign">center</property>
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
(8,74,"resetListBoxRow","resetSinksRow",73,None,None,None,None,None),
|
||||
(8,75,"GtkBox",None,74,None,None,None,None,None),
|
||||
(8,76,"GtkLabel",None,75,None,None,None,None,None),
|
||||
(8,77,"GtkDropDown","resetInputDevice",75,None,None,None,1,None),
|
||||
(8,77,"GtkDropDown","resetSinkDropdown",75,None,None,None,1,None),
|
||||
(8,78,"GtkImage",None,75,None,None,None,2,None),
|
||||
(8,81,"GtkLabel",None,72,None,None,None,1,None),
|
||||
(8,85,"GtkBox","resetInputStreams",56,None,None,None,4,None),
|
||||
|
|
Loading…
Reference in a new issue