fix(audio): identify nodes by PipeWire id, match media.name #22
No reviewers
Labels
No labels
Agent
Ignore
Agent
In Progress
Agent
Planned
Agent
Planning
Agent
Ready
Agent
Triage
Compat
Breaking
Kind
Bug
Kind
Documentation
Kind
Enhancement
Kind
Feature
Kind
Security
Kind
Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
lucas/nanoKontroller2!22
Loading…
Reference in a new issue
No description provided.
Delete branch "agent/issue-18-node-id-identity"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes: #18
What changed
Node identity is the PipeWire bound id.
AudioServicecached nodes in a map keyed bynode.name, which PipeWire does not guarantee to be unique. Everything downstream inherited that: insertion was first-come-wins (siblings were dropped, subscriptions and all),GetMatchingNodesreturned names so identically named streams collapsed to one entry, every actuator re-resolved by name onto that one proxy, andon_node_removederased by name, so one tab ending killed the slot while live siblings remained unreachable. The cache is nowunordered_map<guint32, CachedNode>,GetMatchingNodesreturns ids, andGetMute/SetVolume/SetMute/SetDefaultNode/IsDefaultNode/Get|SetConnectionStateplus all listener callbacks take ids.AudioService::GetNodeName(guint32)covers the two places that genuinely need a name (the default-node API, which addresses by name, and the connection log line).Patterns match a property bag.
NodeMatcher::Matches/FirstMatchingEntrytake aNodeProperties{NodeName, MediaName}and try two candidates per entry: the barenode.name, andnode.name: media.namewhen amedia.nameexists. Both go through the same anchored regex, so a plain name still matches only itself. Entry ranking is unchanged and does not record which candidate matched.Membership is re-evaluated while a node lives. Each
CachedNoderecords the listeners that matched it;notify::propertiestriggersDispatchMatchChanges, which diffs the new matched set against the stored one and emitson_node_availablefor additions andon_node_removedfor removals. A tab retitling into a strip's pattern gets that strip's sticky mute/volume immediately; one retitling out of it stops being written to, and the state it was left in stays.params-changedandports-changeddispatch to the recorded listeners instead of re-matching, since they are not membership changes.Also: both link handlers lost their O(n) scan over the cache (
wp_link_get_linked_object_idsalready yields ids),Action_Connection's self-link guard compares ids, so two different nodes sharing a name are now a valid pair, andReset()disconnects node handlers before clearing the cache so a surviving proxy cannot call back into the service.README's "Specifying nodes" section documents the second candidate, including the consequence that a pattern broad enough to match arbitrary text now also matches through
node.name: media.name, so exclusion lists must account for it.Verification
tests/NodeMatcher_tests.cppcall sites moved to property bags, and a newTestPropertyCandidatescovers the candidate table from the plan (bare name wins over an irrelevantmedia.name; qualified pattern matches only the right title; no qualified candidate without amedia.name; anchoring holds on both candidates) plus the ranking assertion that a qualified entry wins over a later bare-name entry. CI runs them.src/NodeMatcher.cpp(all checks passed). This container has no WirePlumber/glaze dev packages and no root, so the full build and the hardware-dependent checks in the plan's verification section (steps 2 and 3: fan-out across several live Firefox nodes, live re-evaluation on retitling) could not be run here — they need the controller and a PipeWire session.WIP: fix(audio): identify nodes by PipeWire id, match media.nameto fix(audio): identify nodes by PipeWire id, match media.name