feat: Add basic functionality to all audio usecases

This commit is contained in:
Fabio Lenherr / DashieTM 2023-11-14 21:25:39 +01:00
parent 2f1099267a
commit c1984b5b79
32 changed files with 368 additions and 201 deletions

View file

@ -23,13 +23,12 @@ impl InputStreamEntry {
pub fn new(stream: InputStream) -> 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
{
let imp = obj.imp();
imp.resetSinkName.set_text(stream.name.clone().as_str());
let name = stream.application_name.clone() + ": " + stream.name.as_str();
imp.resetSinkName.set_text(name.as_str());
let volume = stream.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
let percentage = (fraction).to_string() + "%";
@ -39,7 +38,6 @@ impl InputStreamEntry {
imp.resetVolumeSlider.connect_change_value(
clone!(@weak imp => @default-return Propagation::Stop, move |_, _, value| {
let fraction = (value / 655.36).round();
println!("{fraction}");
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
set_inputstream_volume(value, imp.stream.clone());
@ -61,7 +59,7 @@ fn set_inputstream_volume(value: f64, stream: Arc<RefCell<InputStream>>) -> bool
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
"/org/xetibo/ReSet",
Duration::from_millis(100),
Duration::from_millis(1000),
);
let res: Result<(bool,), Error> =
proxy.method_call("org.xetibo.ReSet", "SetInputStreamVolume", (stream,));

View file

@ -1,6 +1,6 @@
#![allow(non_snake_case)]
pub mod audioBox;
pub mod audioBoxImpl;
pub mod sinkBox;
pub mod sinkBoxImpl;
pub mod inputStreamEntry;
pub mod inputStreamEntryImpl;
pub mod sinkEntry;

View file

@ -3,31 +3,32 @@ use std::time::Duration;
use crate::components::base::listEntry::ListEntry;
use crate::components::base::utils::Listeners;
use crate::components::output::audioBoxImpl;
use crate::components::output::sinkEntry::set_sink_volume;
use adw::glib::Object;
use adw::prelude::BoxExt;
use adw::prelude::{BoxExt, RangeExt};
use adw::{glib, prelude::ListBoxRowExt};
use dbus::blocking::Connection;
use dbus::Error;
use glib::subclass::prelude::ObjectSubclassIsExt;
use glib::Variant;
use glib::{clone, Propagation, Variant};
use gtk::gio;
use gtk::prelude::ActionableExt;
use ReSet_Lib::audio::audio::{InputStream, Sink};
use super::inputStreamEntry::InputStreamEntry;
use super::sinkBoxImpl;
use super::sinkEntry::SinkEntry;
glib::wrapper! {
pub struct AudioBox(ObjectSubclass<audioBoxImpl::AudioBox>)
pub struct SinkBox(ObjectSubclass<sinkBoxImpl::SinkBox>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
}
unsafe impl Send for AudioBox {}
unsafe impl Sync for AudioBox {}
unsafe impl Send for SinkBox {}
unsafe impl Sync for SinkBox {}
impl AudioBox {
impl SinkBox {
pub fn new() -> Self {
Object::builder().build()
}
@ -47,30 +48,53 @@ impl AudioBox {
}
}
pub fn populate_sinks(output_box: Arc<AudioBox>) {
let output_box_ref = output_box.clone();
pub fn populate_sinks(output_box: Arc<SinkBox>) {
gio::spawn_blocking(move || {
let output_box_imp = output_box.imp();
let output_box_ref = output_box.clone();
{
let output_box_imp = output_box.imp();
output_box_imp.resetDefaultSink.replace(get_default_sink());
}
let sinks = get_sinks();
output_box_imp.resetDefaultSink.replace(get_default_sink());
glib::spawn_future(async move {
glib::idle_add_once(move || {
let output_box_imp = output_box_ref.imp();
// TODO handle default mapping
// output_box_imp.resetVolumePercentage.set_text();
// output_box_imp.resetVolumeSlider.let
for stream in sinks {
// TODO create sink handler -> currently only allows input streams
let entry = ListEntry::new(&SinkEntry::new(stream));
entry.set_activatable(false);
output_box_imp.resetSinks.append(&entry);
let output_box_ref_slider = 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 volume = sink.volume.first().unwrap_or_else(|| &(0 as u32));
let fraction = (*volume as f64 / 655.36).round();
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 {
// TODO create sink handler -> currently only allows input streams
let entry = ListEntry::new(&SinkEntry::new(stream));
entry.set_activatable(false);
output_box_imp.resetSinks.append(&entry);
}
}
output_box_ref
.imp()
.resetVolumeSlider
.connect_change_value(move |_, _, value| {
let imp = output_box_ref_slider.imp();
let fraction = (value / 655.36).round();
println!("{fraction}");
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
set_sink_volume(value, imp.resetDefaultSink.clone());
Propagation::Proceed
});
});
});
});
}
pub fn populate_streams(listeners: Arc<Listeners>, output_box: Arc<AudioBox>) {
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();
@ -122,7 +146,7 @@ fn get_sinks() -> Vec<Sink> {
res.unwrap().0
}
fn get_default_sink() -> Option<Sink> {
fn get_default_sink() -> Sink {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
@ -131,7 +155,7 @@ fn get_default_sink() -> Option<Sink> {
);
let res: Result<(Sink,), Error> = proxy.method_call("org.xetibo.ReSet", "GetDefaultSink", ());
if res.is_err() {
return None;
return Sink::default();
}
Some(res.unwrap().0)
res.unwrap().0
}

View file

@ -2,19 +2,19 @@ use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use crate::components::base::listEntry::ListEntry;
use crate::components::output::audioBox;
use crate::components::output::inputStreamEntry::InputStreamEntry;
use gtk::subclass::prelude::*;
use gtk::{glib, Box, Button, CompositeTemplate, DropDown, Label, TemplateChild};
use gtk::{prelude::*, ProgressBar, Scale};
use ReSet_Lib::audio::audio::{InputStream, Sink};
use super::sinkBox;
use super::sinkEntry::SinkEntry;
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetAudioOutput.ui")]
pub struct AudioBox {
pub struct SinkBox {
#[template_child]
pub resetSinksRow: TemplateChild<ListEntry>,
#[template_child]
@ -33,15 +33,15 @@ pub struct AudioBox {
pub resetInputStreamButton: TemplateChild<ListEntry>,
#[template_child]
pub resetInputStreams: TemplateChild<Box>,
pub resetDefaultSink: RefCell<Option<Sink>>,
pub resetDefaultSink: Arc<RefCell<Sink>>,
pub resetSinkList: Arc<Mutex<Vec<Sink>>>,
pub resetInputStreamList: Arc<Mutex<Vec<InputStream>>>,
}
#[glib::object_subclass]
impl ObjectSubclass for AudioBox {
impl ObjectSubclass for SinkBox {
const NAME: &'static str = "resetAudioOutput";
type Type = audioBox::AudioBox;
type Type = sinkBox::SinkBox;
type ParentType = gtk::Box;
fn class_init(klass: &mut Self::Class) {
@ -56,19 +56,19 @@ impl ObjectSubclass for AudioBox {
}
}
impl BoxImpl for AudioBox {}
impl BoxImpl for SinkBox {}
impl ObjectImpl for AudioBox {
impl ObjectImpl for SinkBox {
fn constructed(&self) {
let obj = self.obj();
obj.setupCallbacks();
}
}
impl ListBoxRowImpl for AudioBox {}
impl ListBoxRowImpl for SinkBox {}
impl WidgetImpl for AudioBox {}
impl WidgetImpl for SinkBox {}
impl WindowImpl for AudioBox {}
impl WindowImpl for SinkBox {}
impl ApplicationWindowImpl for AudioBox {}
impl ApplicationWindowImpl for SinkBox {}

View file

@ -42,7 +42,7 @@ impl SinkEntry {
println!("{fraction}");
let percentage = (fraction).to_string() + "%";
imp.resetVolumePercentage.set_text(&percentage);
set_inputstream_volume(value, imp.stream.clone());
set_sink_volume(value, imp.stream.clone());
Propagation::Proceed
}),
);
@ -51,7 +51,7 @@ impl SinkEntry {
}
}
fn set_inputstream_volume(value: f64, stream: Arc<RefCell<Sink>>) -> bool {
pub fn set_sink_volume(value: f64, stream: Arc<RefCell<Sink>>) -> bool {
let mut stream = stream.borrow_mut().clone();
// let x = stream.volume.iter_mut().map(|_| value as u32);
stream.volume = vec![value as u32; stream.channels as usize];
@ -61,7 +61,7 @@ fn set_inputstream_volume(value: f64, stream: Arc<RefCell<Sink>>) -> bool {
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
"/org/xetibo/ReSet",
Duration::from_millis(100),
Duration::from_millis(1000),
);
let res: Result<(bool,), Error> =
proxy.method_call("org.xetibo.ReSet", "SetSinkVolume", (stream,));