Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1,231 changes: 630 additions & 601 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", "crates/*", "page", "pages/*", "subscriptions/*"]
members = ["cosmic-settings", "page", "pages/*", "subscriptions/*"]
default-members = ["cosmic-settings"]
resolver = "3"

Expand Down
14 changes: 10 additions & 4 deletions cosmic-settings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ cosmic-settings-a11y-manager-subscription = { path = "../subscriptions/a11y-mana
cosmic-settings-airplane-mode-subscription = { path = "../subscriptions/airplane-mode", optional = true }
cosmic-settings-bluetooth-subscription = { path = "../subscriptions/bluetooth", optional = true }
cosmic-settings-network-manager-subscription = { path = "../subscriptions/network-manager", optional = true }
cosmic-settings-sound = { path = "../pages/sound", optional = true }
cosmic-settings-upower-subscription = { path = "../subscriptions/upower", optional = true }
cosmic-settings-sound-subscription = { path = "../subscriptions/sound", optional = true, features = [
"auto-profile-init",
] }
cosmic-settings-wallpaper = { path = "../pages/wallpapers" }
cosmic-settings-daemon-config = { git = "https://github.com/pop-os/cosmic-settings-daemon", optional = true }
derive_setters = "0.1.9"
Expand Down Expand Up @@ -98,6 +96,14 @@ gettext-rs = { version = "0.7.7", features = [
num-traits = "0.2"
pwhash = "1"
which = "8.0.0"
zlink = "0.5.0"
intmap = "3.1.3"

[dependencies.cosmic-settings-audio-client]
git = "https://github.com/pop-os/cosmic-settings-daemon"
branch = "varlink"
features = ["codec"]
optional = true

[dependencies.icu]
version = "2.1.1"
Expand Down Expand Up @@ -183,7 +189,7 @@ page-region = [
"dep:zbus",
"dep:accounts-zbus",
]
page-sound = ["dep:cosmic-settings-sound-subscription"]
page-sound = ["dep:cosmic-settings-audio-client", "dep:cosmic-settings-sound"]
page-users = ["xdg-portal", "dep:accounts-zbus", "dep:zbus", "dep:zbus_polkit"]
page-window-management = ["cosmic-comp-config", "dep:cosmic-settings-config"]
page-workspaces = ["cosmic-comp-config"]
Expand Down
101 changes: 72 additions & 29 deletions cosmic-settings/src/pages/sound/device_profiles.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
// Copyright 2025 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only

use cosmic::{Apply, widget};
use super::model;
use cosmic::iced::futures;
use cosmic::{Apply, iced, widget};
use cosmic_settings_audio_client::{self as audio_client, CosmicAudioProxy};
use cosmic_settings_page::{self as page, Section, section};
use cosmic_settings_sound_subscription::{self as subscription};
use futures::executor::block_on;
use slotmap::SlotMap;
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;

#[derive(Clone, Debug)]
pub enum Message {}
pub enum Message {
/// Update for the model.
Model(cosmic_settings_sound::Message),
/// Set the profile of a sound device.
SetProfile(u32, u32),
/// Surface Action
Surface(cosmic::surface::Action),
}

impl From<Message> for crate::pages::Message {
fn from(message: Message) -> Self {
Expand All @@ -24,6 +37,8 @@ impl From<Message> for crate::Message {
#[derive(Default)]
pub struct Page {
entity: page::Entity,
model: model::Model,
client: Option<Rc<RefCell<audio_client::Client>>>,
}

impl page::AutoBind<crate::pages::Message> for Page {}
Expand All @@ -41,55 +56,83 @@ impl page::Page<crate::pages::Message> for Page {
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())
fn on_leave(&mut self) -> cosmic::Task<crate::pages::Message> {
*self = Page {
entity: self.entity,
..Page::default()
};
cosmic::Task::none()
}

fn subscription(&self, _core: &cosmic::Core) -> iced::Subscription<crate::pages::Message> {
iced::Subscription::run(|| {
iced::stream::channel(
1,
move |emitter: futures::channel::mpsc::Sender<crate::pages::Message>| async move {
cosmic_settings_sound::subscribe(emitter, |m| Message::Model(m).into()).await
},
)
})
}
}

impl Page {
pub fn update(&mut self, _message: Message) -> cosmic::Task<crate::app::Message> {
pub fn update(&mut self, message: Message) -> cosmic::Task<crate::app::Message> {
match message {
Message::Model(cosmic_settings_sound::Message::Subscription(message)) => {
self.model.update(message);
}

Message::Model(cosmic_settings_sound::Message::Client(client)) => {
if let Some(client) = Arc::into_inner(client) {
self.client = Some(Rc::new(RefCell::new(client)));
self.model = model::Model {
text: model::Text {
hd_audio: fl!("sound-hd-audio"),
usb_audio: fl!("sound-usb-audio"),
},
..model::Model::default()
};
}
}

Message::Surface(a) => return cosmic::task::message(crate::app::Message::Surface(a)),

Message::SetProfile(id, index) => {
if let Some(client) = self.client.clone() {
block_on(async move {
_ = client.borrow_mut().conn.set_profile(id, index, true).await;
});
}
}
}

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)| {
Section::default().view::<Page>(move |_, page, _section| {
let devices = 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]),
move |id| Message::SetProfile(device_id, indexes[id]),
cosmic::iced::window::Id::RESERVED,
super::Message::Surface,
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()
})
Expand Down
Loading