fix(sound): only consider active routes when setting volume and mute-ness
This commit is contained in:
parent
9db1681e0d
commit
1139e34928
3 changed files with 71 additions and 32 deletions
|
|
@ -66,17 +66,18 @@ fn run_service(
|
|||
let registry = core.get_registry_rc()?;
|
||||
|
||||
let state = Rc::new(RefCell::new(State {
|
||||
nodes: IntMap::new(),
|
||||
main_loop: main_loop.downgrade(),
|
||||
proxies: Proxies {
|
||||
devices: IntMap::new(),
|
||||
metadata: IntMap::new(),
|
||||
nodes: IntMap::new(),
|
||||
},
|
||||
nodes: IntMap::new(),
|
||||
active_routes: IntMap::new(),
|
||||
routes: IntMap::new(),
|
||||
node_devices: IntMap::new(),
|
||||
node_card_profile_device: IntMap::new(),
|
||||
node_props: IntMap::new(),
|
||||
main_loop: main_loop.downgrade(),
|
||||
on_event,
|
||||
}));
|
||||
|
||||
|
|
@ -207,7 +208,9 @@ fn run_service(
|
|||
match param_type {
|
||||
ParamType::EnumProfile => {
|
||||
if let Some(profile) = Profile::from_pod(pod) {
|
||||
state.borrow_mut().add_profile(device_id, profile);
|
||||
state
|
||||
.borrow_mut()
|
||||
.add_profile(device_id, index, profile);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +426,7 @@ pub enum Event {
|
|||
/// A new node was detected.
|
||||
AddNode(Node),
|
||||
/// A profile was enumerated
|
||||
AddProfile(DeviceId, Profile),
|
||||
AddProfile(DeviceId, u32, Profile),
|
||||
/// A route was enumerated
|
||||
AddRoute(DeviceId, u32, Route),
|
||||
/// The default sink was changed.
|
||||
|
|
@ -496,13 +499,21 @@ struct Proxies {
|
|||
}
|
||||
|
||||
struct State {
|
||||
nodes: IntMap<PipewireId, (NodeId, Option<DeviceId>)>,
|
||||
pub(self) proxies: Proxies,
|
||||
routes: IntMap<DeviceId, Vec<Route>>,
|
||||
node_devices: IntMap<NodeId, DeviceId>,
|
||||
node_props: IntMap<NodeId, NodeProps>,
|
||||
node_card_profile_device: IntMap<NodeId, u32>,
|
||||
main_loop: MainLoopWeak,
|
||||
/// Stores pipewire objects that we are monitoring.
|
||||
pub(self) proxies: Proxies,
|
||||
/// Associates the pipewire ID of a node to its node and device IDs.
|
||||
nodes: IntMap<PipewireId, (NodeId, Option<DeviceId>)>,
|
||||
/// Routes which are currently in use by devices.
|
||||
active_routes: IntMap<DeviceId, Vec<Route>>,
|
||||
/// Routes which are supported by devices.
|
||||
routes: IntMap<DeviceId, Vec<Route>>,
|
||||
/// Associates node objects to their device objects.
|
||||
node_devices: IntMap<NodeId, DeviceId>,
|
||||
/// Additional properties of nodes for managing volume, mute, etc.
|
||||
node_props: IntMap<NodeId, NodeProps>,
|
||||
/// Associates a node with a card profile device for matching nodes to routes.
|
||||
node_card_profile_device: IntMap<NodeId, u32>,
|
||||
/// Handle events and exit the loop when `true` is returned.
|
||||
on_event: Box<dyn FnMut(Event)>,
|
||||
}
|
||||
|
|
@ -513,6 +524,16 @@ impl State {
|
|||
}
|
||||
|
||||
fn active_route(&mut self, id: DeviceId, index: u32, route: Route) {
|
||||
// Keep a record of routes attached to a device for setting properties.
|
||||
// This will overwrite routes on updates to
|
||||
let routes = self.active_routes.entry(id).or_default();
|
||||
if routes.len() < index as usize + 1 {
|
||||
let additional = (index as usize + 1) - routes.capacity();
|
||||
routes.reserve_exact(additional);
|
||||
routes.extend(std::iter::repeat(Route::default()).take(additional));
|
||||
}
|
||||
routes[index as usize] = route.clone();
|
||||
|
||||
self.on_event(Event::ActiveRoute(id, index, route));
|
||||
}
|
||||
|
||||
|
|
@ -554,8 +575,8 @@ impl State {
|
|||
self.on_event(Event::AddNode(node));
|
||||
}
|
||||
|
||||
fn add_profile(&mut self, id: DeviceId, profile: Profile) {
|
||||
self.on_event(Event::AddProfile(id, profile));
|
||||
fn add_profile(&mut self, id: DeviceId, index: u32, profile: Profile) {
|
||||
self.on_event(Event::AddProfile(id, index, profile));
|
||||
}
|
||||
|
||||
fn add_route(&mut self, id: DeviceId, index: u32, route: Route) {
|
||||
|
|
@ -592,8 +613,8 @@ impl State {
|
|||
self.on_event(Event::DefaultSource(name));
|
||||
}
|
||||
|
||||
fn node_route(&self, device_id: DeviceId, route_device: i32) -> Option<&Route> {
|
||||
self.routes
|
||||
fn active_node_route(&self, device_id: DeviceId, route_device: i32) -> Option<&Route> {
|
||||
self.active_routes
|
||||
.get(device_id)?
|
||||
.iter()
|
||||
.find(|r| r.devices.contains(&route_device))
|
||||
|
|
@ -682,14 +703,14 @@ impl State {
|
|||
fn set_mute_node(&self, id: NodeId, mute: bool) {
|
||||
// Prefer to mute the device instead of the node.
|
||||
// Muting a node will not emit a notification.
|
||||
if let Some((&device_id, &route_device)) = self
|
||||
if let Some((&device_id, &card_profile_device)) = self
|
||||
.node_devices
|
||||
.get(id)
|
||||
.zip(self.node_card_profile_device.get(id))
|
||||
{
|
||||
let route_device = route_device as i32;
|
||||
if let Some(route) = self.node_route(device_id, route_device) {
|
||||
self.set_mute(device_id, route_device, route, mute);
|
||||
let card_profile_device = card_profile_device as i32;
|
||||
if let Some(route) = self.active_node_route(device_id, card_profile_device) {
|
||||
self.set_mute(device_id, card_profile_device, route, mute);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
|
@ -762,14 +783,21 @@ impl State {
|
|||
};
|
||||
|
||||
// Prefer to change the volume of the device instead of the node.
|
||||
if let Some((&device_id, &route_device)) = self
|
||||
if let Some((&device_id, &card_profile_device)) = self
|
||||
.node_devices
|
||||
.get(id)
|
||||
.zip(self.node_card_profile_device.get(id))
|
||||
{
|
||||
let route_device = route_device as i32;
|
||||
if let Some(route) = self.node_route(device_id, route_device) {
|
||||
self.set_volume(device_id, props, route_device, route, volume, balance);
|
||||
let card_profile_device = card_profile_device as i32;
|
||||
if let Some(route) = self.active_node_route(device_id, card_profile_device) {
|
||||
self.set_volume(
|
||||
device_id,
|
||||
props,
|
||||
card_profile_device,
|
||||
route,
|
||||
volume,
|
||||
balance,
|
||||
);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
use crate::{Availability, spa_utils::string_from_pod};
|
||||
use libspa::pod::Pod;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Profile {
|
||||
pub index: i32,
|
||||
pub priority: i32,
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ impl Model {
|
|||
}
|
||||
}
|
||||
|
||||
pipewire::Event::AddProfile(id, profile) => {
|
||||
pipewire::Event::AddProfile(id, index, profile) => {
|
||||
if let Some(p) = self.active_profiles.get_mut(id) {
|
||||
if p.index == profile.index {
|
||||
*p = profile.clone();
|
||||
|
|
@ -534,16 +534,17 @@ impl Model {
|
|||
}
|
||||
|
||||
let profiles = self.device_profiles.entry(id).or_default();
|
||||
for p in profiles.iter_mut() {
|
||||
if p.index == profile.index {
|
||||
*p = profile;
|
||||
|
||||
self.update_ui_profiles();
|
||||
return;
|
||||
}
|
||||
if profiles.len() < index as usize + 1 {
|
||||
let additional = (index as usize + 1) - profiles.capacity();
|
||||
profiles.reserve_exact(additional);
|
||||
profiles.extend(std::iter::repeat_n(
|
||||
pipewire::Profile::default(),
|
||||
additional,
|
||||
));
|
||||
}
|
||||
|
||||
profiles.push(profile);
|
||||
profiles[index as usize] = profile;
|
||||
|
||||
self.update_ui_profiles();
|
||||
}
|
||||
|
||||
|
|
@ -676,12 +677,22 @@ impl Model {
|
|||
|
||||
fn add_route(&mut self, id: DeviceId, index: u32, route: pipewire::Route) {
|
||||
self.update_device_route_name(&route, id);
|
||||
|
||||
tracing::debug!(target: "sound",
|
||||
"Device {} added route {} ({:?}); {:?}",
|
||||
id,
|
||||
route.name,
|
||||
route.direction,
|
||||
route.available
|
||||
);
|
||||
|
||||
let routes = self.device_routes.entry(id).or_default();
|
||||
if routes.len() < index as usize + 1 {
|
||||
let additional = (index as usize + 1) - routes.capacity();
|
||||
routes.reserve_exact(additional);
|
||||
routes.extend(std::iter::repeat_n(pipewire::Route::default(), additional));
|
||||
}
|
||||
|
||||
routes[index as usize] = route;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue