Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f02fe2c
fix(resources): change desktop entry Types to Application
mmstick Nov 5, 2025
3e05fe8
feat(sound): redesign with separate device profiles page
mmstick Oct 20, 2025
317306e
feat(sound): drop libpulse & set volume, balance, profiles, etc. with…
mmstick Nov 14, 2025
a0d440d
chore(debian): drop libpulse dependency
mmstick Nov 14, 2025
fa6d081
fix(sound): switch to cubic channel volumes
mmstick Nov 14, 2025
0f3d9b2
fix(sound): set profile with pw-cli again
mmstick Nov 17, 2025
4304ebc
fix(sound): get the correct route device index from nodes
mmstick Nov 17, 2025
82148fb
fix(sound): wrong property for input mute status
mmstick Nov 17, 2025
343d7f6
fix(sound): enumerate EnumProfile(s) on device changes
mmstick Nov 17, 2025
a1aec98
fix(sound): also update the active profile's profile
mmstick Nov 17, 2025
e04b133
fix(sound): display unavailable profile if it is active
mmstick Nov 18, 2025
dbaa909
perf(sound): cache sound device profiles
mmstick Nov 18, 2025
7d9f224
chore: update libcosmic
mmstick Nov 18, 2025
febc892
fix(sound): on active device profile change, avoid reset if we set it
mmstick Nov 18, 2025
43df535
fix(sound): allow changing volume/mute of non-active routes
mmstick Nov 18, 2025
365c848
fix(sound): avoid slider changes while volume is being debounced
mmstick Nov 18, 2025
6df7f4c
fix(sound): tweak volume debounce rate
mmstick Nov 18, 2025
2e6aebe
fix(sound): use pactl set-default-{source|sink} for virtual sinks
mmstick Nov 18, 2025
9c95cda
chore(sound): add code comments
mmstick Nov 18, 2025
28230bc
chore(sound): move pipewire logic to cosmic-pipewire crate
mmstick Nov 18, 2025
8b74831
fix(sound): active route may overwrite other routes
mmstick Nov 19, 2025
dbc5b35
fix(sound): update profiles on active profile change
mmstick Nov 19, 2025
4ed196c
feat(sound): auto-select first available profile if device is `Off`
mmstick Nov 19, 2025
2bdb106
chore(sound): auto-select profile only when enabled in model
mmstick Nov 19, 2025
5b24878
fix(sound): regression in active route not being added to device name
mmstick Nov 20, 2025
274e2a9
refactor(sound): dedupe code to update device route name
mmstick Nov 20, 2025
c1a5a11
fix(sound): update ui profiles after setting profile from UI
mmstick Nov 20, 2025
dc59469
fix(sound): alter where device reselect occurs
mmstick Nov 20, 2025
609661c
fix(sound): reuse set_profile method to track last set profiles
mmstick Nov 20, 2025
7a02883
feat(sound): make save property configurable; only save when user sel…
mmstick Nov 20, 2025
7ce2abf
fix(sound): remove broken profile auto-select for off devices
mmstick Nov 20, 2025
97ad1c2
chore: improve RUST_LOG handling
mmstick Nov 20, 2025
7a2e297
fix(sound): add logs & remove device / profile auto-select
mmstick Nov 21, 2025
5bb27f8
fix(sound): unset active sink/source if node was removed
mmstick Nov 21, 2025
fdbc6c1
feat(sound): retain sink/source device on saved profile change if dev…
mmstick Nov 21, 2025
a44fc56
feat(sound): retain active sink/source device on external profile change
mmstick Nov 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
327 changes: 173 additions & 154 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["cosmic-settings", "page", "pages/*", "subscriptions/*"]
members = ["cosmic-settings", "crates/*", "page", "pages/*", "subscriptions/*"]
default-members = ["cosmic-settings"]
resolver = "3"

Expand Down
4 changes: 2 additions & 2 deletions cosmic-settings/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cosmic-settings"
version = "0.1.0"
version = "1.0.0-beta6"
edition = "2024"
license = "GPL-3.0-only"
publish = false
Expand Down Expand Up @@ -72,7 +72,7 @@ tachyonix = "0.3.1"
timedate-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
tokio = { workspace = true, features = ["fs", "io-util", "sync"] }
tracing = "0.1.41"
tracing-subscriber = "0.3.20"
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
udev = { version = "0.9.3", optional = true }
upower_dbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
bluez-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
Expand Down
7 changes: 7 additions & 0 deletions cosmic-settings/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,13 @@ impl cosmic::Application for SettingsApp {
}
}

#[cfg(feature = "page-sound")]
crate::pages::Message::SoundDeviceProfiles(message) => {
if let Some(page) = self.pages.page_mut::<sound::device_profiles::Page>() {
return page.update(message).map(Into::into);
}
}

crate::pages::Message::StartupApps(message) => {
if let Some(page) = self.pages.page_mut::<applications::startup_apps::Page>() {
return page.update(message).map(Into::into);
Expand Down
22 changes: 7 additions & 15 deletions cosmic-settings/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,6 @@ fn init_localizer() {
}

fn init_logger() {
let log_level = std::env::var("RUST_LOG")
.ok()
.and_then(|level| level.parse::<tracing::Level>().ok())
.unwrap_or(tracing::Level::INFO);

let log_format = tracing_subscriber::fmt::format()
.pretty()
.without_time()
Expand All @@ -214,17 +209,14 @@ fn init_logger() {
.with_target(false)
.with_thread_names(true);

let log_filter = tracing_subscriber::fmt::Layer::default()
let log_layer = tracing_subscriber::fmt::Layer::default()
.with_writer(std::io::stderr)
.event_format(log_format)
.with_filter(tracing_subscriber::filter::filter_fn(move |metadata| {
let target = metadata.target();
metadata.level() == &tracing::Level::ERROR
|| ((target.starts_with("cosmic_settings") || target.starts_with("cosmic_bg"))
&& metadata.level() <= &log_level)
}));

tracing_subscriber::registry().with(log_filter).init();
.event_format(log_format);

tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::from_env("RUST_LOG"))
.with(log_layer)
.init();
}

#[macro_export]
Expand Down
2 changes: 2 additions & 0 deletions cosmic-settings/src/pages/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub enum Message {
Region(time::region::Message),
#[cfg(feature = "page-sound")]
Sound(sound::Message),
#[cfg(feature = "page-sound")]
SoundDeviceProfiles(sound::device_profiles::Message),
StartupApps(applications::startup_apps::Message),
#[cfg(feature = "page-users")]
User(system::users::Message),
Expand Down
96 changes: 96 additions & 0 deletions cosmic-settings/src/pages/sound/device_profiles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2025 System76 <[email protected]>
// SPDX-License-Identifier: GPL-3.0-only

use cosmic::{Apply, widget};
use cosmic_settings_page::{self as page, Section, section};
use cosmic_settings_sound_subscription::{self as subscription};
use slotmap::SlotMap;

#[derive(Clone, Debug)]
pub enum Message {}

impl From<Message> for crate::pages::Message {
fn from(message: Message) -> Self {
crate::pages::Message::SoundDeviceProfiles(message)
}
}

impl From<Message> for crate::Message {
fn from(message: Message) -> Self {
crate::Message::PageMessage(message.into())
}
}

#[derive(Default)]
pub struct Page {
entity: page::Entity,
}

impl page::AutoBind<crate::pages::Message> for Page {}

impl page::Page<crate::pages::Message> for Page {
fn info(&self) -> page::Info {
page::Info::new("sound-device-profiles", "preferences-sound-symbolic")
.title(fl!("sound-device-profiles"))
}

fn content(
&self,
sections: &mut SlotMap<section::Entity, Section<crate::pages::Message>>,
) -> Option<page::Content> {
Some(vec![sections.insert(view())])
}

fn on_leave(&mut self) -> cosmic::Task<crate::pages::Message> {
cosmic::Task::done(crate::pages::Message::Sound(super::Message::Reload))
}

fn set_id(&mut self, entity: cosmic_settings_page::Entity) {
self.entity = entity;
}

fn subscription(
&self,
_core: &cosmic::Core,
) -> cosmic::iced::Subscription<crate::pages::Message> {
cosmic::iced::Subscription::run(subscription::watch)
.map(|message| super::Message::Subscription(message).into())
}
}

impl Page {
pub fn update(&mut self, _message: Message) -> cosmic::Task<crate::app::Message> {
cosmic::Task::none()
}
}

pub fn view() -> Section<crate::pages::Message> {
Section::default().view::<Page>(move |binder, _page, _section| {
let sound_page_id = binder.find_page_by_id("sound").unwrap().0;
let sound_page = binder.page[sound_page_id]
.downcast_ref::<super::Page>()
.unwrap();

let devices = sound_page
.model
.device_profile_dropdowns
.iter()
.cloned()
.map(|(device_id, name, active_profile, indexes, descriptions)| {
let dropdown = widget::dropdown::popup_dropdown(
descriptions,
active_profile,
move |id| super::Message::SetProfile(device_id, indexes[id]),
cosmic::iced::window::Id::RESERVED,
super::Message::Surface,
crate::Message::from,
)
.apply(cosmic::Element::from)
.map(crate::pages::Message::from);

widget::settings::item::builder(name).control(dropdown)
});

widget::settings::section().extend(devices).into()
})
}
Loading