Merge pull request #55 from Xetibo/dashie

feat: Add dropdowns
This commit is contained in:
takotori 2023-11-15 14:59:38 +01:00 committed by GitHub
commit e0375b7b45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 297 additions and 54 deletions

View file

@ -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
}

View file

@ -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 {}

View file

@ -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);
}

View file

@ -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]

View file

@ -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();

View file

@ -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
}

View file

@ -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]

View file

@ -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);
}

View file

@ -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]

View file

@ -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 {

View file

@ -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)]

View file

@ -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>

View file

@ -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),