feat: sound balance
This commit is contained in:
parent
f153bf3797
commit
d8edef49f4
6 changed files with 131 additions and 16 deletions
47
Cargo.lock
generated
47
Cargo.lock
generated
|
|
@ -1771,19 +1771,20 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-settings-subscriptions"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/cosmic-settings-subscriptions?branch=eap-peap#ad9c0d0d2df220b8c9336602be8458227e162b74"
|
||||
source = "git+https://github.com/pop-os/cosmic-settings-subscriptions?branch=sound#9c9b87dca2822060dbd776a4fb714902b6bab5e5"
|
||||
dependencies = [
|
||||
"bluez-zbus",
|
||||
"cosmic-dbus-networkmanager",
|
||||
"futures",
|
||||
"iced_futures",
|
||||
"itertools 0.13.0",
|
||||
"itertools 0.14.0",
|
||||
"libpulse-binding",
|
||||
"log",
|
||||
"os_pipe",
|
||||
"pipewire",
|
||||
"rustix 0.38.44",
|
||||
"rustix 1.0.3",
|
||||
"secure-string",
|
||||
"thiserror 1.0.69",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
|
|
@ -4088,6 +4089,15 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
|
|
@ -4592,6 +4602,12 @@ version = "0.6.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.7.4"
|
||||
|
|
@ -5484,6 +5500,16 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_pipe"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ouroboros"
|
||||
version = "0.18.5"
|
||||
|
|
@ -6428,6 +6454,19 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.3",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.19"
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ num-derive = "0.4"
|
|||
|
||||
[dependencies.cosmic-settings-subscriptions]
|
||||
git = "https://github.com/pop-os/cosmic-settings-subscriptions"
|
||||
branch = "eap-peap"
|
||||
branch = "sound"
|
||||
#TODO: only select features as needed
|
||||
features = ["network_manager", "pipewire", "pulse", "bluetooth"]
|
||||
optional = true
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ fn zoom_shortcuts() -> (Vec<Binding>, Vec<Binding>) {
|
|||
let Some(config) = shortcuts::context().ok() else {
|
||||
return (Vec::new(), Vec::new());
|
||||
};
|
||||
let shortcuts = dbg!(shortcuts::shortcuts(&config));
|
||||
let shortcuts = shortcuts::shortcuts(&config);
|
||||
|
||||
let zoom_in = shortcuts
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -8,19 +8,18 @@ use std::{
|
|||
|
||||
use anyhow::Context;
|
||||
use cosmic::{
|
||||
Apply, Element, Task,
|
||||
iced::{Alignment, Length},
|
||||
iced_core::text::Wrapping,
|
||||
iced_widget::focus_next,
|
||||
widget::{self, column, icon},
|
||||
Apply, Element, Task,
|
||||
};
|
||||
use cosmic_settings_page::{self as page, section, Section};
|
||||
use cosmic_settings_page::{self as page, Section, section};
|
||||
use cosmic_settings_subscriptions::network_manager::{
|
||||
self,
|
||||
self, NetworkManagerState,
|
||||
available_wifi::{AccessPoint, NetworkType},
|
||||
current_networks::ActiveConnectionInfo,
|
||||
hw_address::HwAddress,
|
||||
NetworkManagerState,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use secure_string::SecureString;
|
||||
|
|
@ -526,7 +525,7 @@ impl Page {
|
|||
return cosmic::task::batch(vec![
|
||||
self.connect(conn.clone()),
|
||||
connection_settings(conn),
|
||||
])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
use std::{collections::BTreeMap, time::Duration};
|
||||
|
||||
use cosmic::{
|
||||
iced::{window, Alignment, Length},
|
||||
Element, Task,
|
||||
iced::{Alignment, Length, window},
|
||||
surface,
|
||||
widget::{self, settings},
|
||||
Element, Task,
|
||||
};
|
||||
use cosmic_settings_page::{self as page, section, Section};
|
||||
use cosmic_settings_page::{self as page, Section, section};
|
||||
use cosmic_settings_subscriptions::{pipewire, pulse};
|
||||
use futures::StreamExt;
|
||||
use indexmap::IndexMap;
|
||||
|
|
@ -33,8 +33,12 @@ pub enum Message {
|
|||
SinkProfileSelect(DeviceId),
|
||||
/// Request to change the default output volume.
|
||||
SinkVolumeChanged(u32),
|
||||
/// Request to change the default output balance.
|
||||
SinkBalanceChanged(u32),
|
||||
/// Change the output volume.
|
||||
SinkVolumeApply(NodeId),
|
||||
/// Change the output balance.
|
||||
SinkBalanceApply,
|
||||
/// Toggle the mute status of the output.
|
||||
SinkMuteToggle,
|
||||
/// Change the default input output.
|
||||
|
|
@ -89,6 +93,10 @@ pub struct Page {
|
|||
sink_mute: bool,
|
||||
sink_volume_debounce: bool,
|
||||
|
||||
sink_balance: Option<f32>,
|
||||
sink_balance_text: Option<String>,
|
||||
sink_balance_debounce: bool,
|
||||
sink_channels: Option<pulse::PulseChannels>,
|
||||
source_volume: u32,
|
||||
source_volume_text: String,
|
||||
source_mute: bool,
|
||||
|
|
@ -346,6 +354,26 @@ impl Page {
|
|||
return command;
|
||||
}
|
||||
}
|
||||
Message::SinkBalanceChanged(balance) => {
|
||||
self.sink_balance = Some((balance as f32 - 100.) / 100.);
|
||||
self.sink_balance_text = Some(format!("{balance:.2}"));
|
||||
if self.sink_balance_debounce {
|
||||
return Task::none();
|
||||
}
|
||||
|
||||
let mut command = None;
|
||||
if let Some(&node_id) = self.sink_ids.get(self.active_sink.unwrap_or(0)) {
|
||||
command = Some(cosmic::task::future(async move {
|
||||
tokio::time::sleep(Duration::from_millis(64)).await;
|
||||
crate::pages::Message::Sound(Message::SinkBalanceApply)
|
||||
}));
|
||||
}
|
||||
|
||||
if let Some(command) = command {
|
||||
self.sink_balance_debounce = true;
|
||||
return command;
|
||||
}
|
||||
}
|
||||
Message::Pulse(pulse::Event::SinkVolume(volume)) => {
|
||||
if self.sink_volume_debounce {
|
||||
return Task::none();
|
||||
|
|
@ -381,6 +409,13 @@ impl Page {
|
|||
self.active_profiles
|
||||
.insert(device_id, card.active_profile.map(|p| p.name));
|
||||
}
|
||||
Message::Pulse(pulse::Event::Balance(balance)) => {
|
||||
self.sink_balance = balance;
|
||||
self.sink_balance_text = balance.map(|b| format!("{b:.2}"));
|
||||
}
|
||||
Message::Pulse(pulse::Event::Channels(channels)) => {
|
||||
self.sink_channels = Some(channels);
|
||||
}
|
||||
Message::Pipewire(pipewire::DeviceEvent::Add(device)) => {
|
||||
let device_id = match device.variant {
|
||||
pipewire::DeviceVariant::Alsa { alsa_card, .. } => DeviceId::Alsa(alsa_card),
|
||||
|
|
@ -494,9 +529,19 @@ impl Page {
|
|||
}
|
||||
}
|
||||
}
|
||||
Message::SinkVolumeApply(node_id) => {
|
||||
Message::SinkBalanceApply => {
|
||||
self.sink_balance_debounce = false;
|
||||
if let Some((balance, channels)) =
|
||||
self.sink_balance.zip(self.sink_channels.as_mut())
|
||||
{
|
||||
channels.set_balance(balance);
|
||||
}
|
||||
}
|
||||
Message::SinkVolumeApply(_) => {
|
||||
self.sink_volume_debounce = false;
|
||||
wpctl_set_volume(node_id, self.sink_volume);
|
||||
if let Some(channels) = self.sink_channels.as_mut() {
|
||||
channels.set_volume(self.sink_volume as f32 / 100.);
|
||||
}
|
||||
}
|
||||
Message::SourceVolumeApply(node_id) => {
|
||||
self.source_volume_debounce = false;
|
||||
|
|
@ -656,6 +701,9 @@ fn output() -> Section<crate::pages::Message> {
|
|||
let device = descriptions.insert(fl!("sound-output", "device"));
|
||||
let _level = descriptions.insert(fl!("sound-output", "level"));
|
||||
let profile = descriptions.insert(fl!("profile"));
|
||||
let balance = descriptions.insert(fl!("sound-output", "balance"));
|
||||
let left = descriptions.insert(fl!("sound-output", "left"));
|
||||
let right = descriptions.insert(fl!("sound-output", "right"));
|
||||
// let balance = descriptions.insert(fl!("sound-output", "balance"));
|
||||
|
||||
Section::default()
|
||||
|
|
@ -712,6 +760,33 @@ fn output() -> Section<crate::pages::Message> {
|
|||
|
||||
controls = controls.add(settings::item(&*section.descriptions[profile], dropdown));
|
||||
}
|
||||
if let Some(sink_balance) = page.sink_balance {
|
||||
controls = controls.add(settings::item(
|
||||
&*section.descriptions[balance],
|
||||
widget::row::with_capacity(4)
|
||||
.align_y(Alignment::Center)
|
||||
.push(
|
||||
widget::text::body(&*section.descriptions[left])
|
||||
.width(Length::Fixed(22.0))
|
||||
.align_x(Alignment::Center),
|
||||
)
|
||||
.push(widget::horizontal_space().width(8))
|
||||
.push(
|
||||
widget::slider(
|
||||
0..=200,
|
||||
((sink_balance + 1.).max(0.) * 100.).round() as u32,
|
||||
Message::SinkBalanceChanged,
|
||||
)
|
||||
.breakpoints(&[100]),
|
||||
)
|
||||
.push(widget::horizontal_space().width(8))
|
||||
.push(
|
||||
widget::text::body(&*section.descriptions[right])
|
||||
.width(Length::Fixed(22.0))
|
||||
.align_x(Alignment::Center),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Element::from(controls).map(crate::pages::Message::Sound)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -449,6 +449,8 @@ sound-output = Output
|
|||
.level = Output level
|
||||
.config = Configuration
|
||||
.balance = Balance
|
||||
.left = Left
|
||||
.right = Right
|
||||
|
||||
sound-input = Input
|
||||
.volume = Input volume
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue