Skip to content

Tahoe compat#852

Open
GloryWord wants to merge 10 commits intokyleneideck:masterfrom
GloryWord:tahoe-compat
Open

Tahoe compat#852
GloryWord wants to merge 10 commits intokyleneideck:masterfrom
GloryWord:tahoe-compat

Conversation

@GloryWord
Copy link
Copy Markdown

No description provided.

Recent post-v0.4.3 Tahoe reports pointed to two failure modes that made
Background Music feel unsafe to use: aggregate output devices could lose
usable volume controls, and quitting or uninstalling could leave the
system stuck at the wrong volume. This change pulls the minimal proven
fixes onto a single branch so Tahoe users can build from source without
reopening the broader helper/ducking design.

The aggregate-device lane now treats aggregate outputs as special cases
for control detection and skips deprecated volume/mute sync paths that
can corrupt System Settings state. The termination lane deactivates
control-sync and playthrough before restoring the default device, and the
uninstall path removes stale BGM device preference entries that can keep
incorrect volume state alive across restarts.

Constraint: Must stay close to upstream master to preserve CoreAudio behavior and ease future rebases
Constraint: Cannot fully verify privileged install/runtime helper behavior in this environment because sudo is unavailable
Rejected: Large Tahoe-specific refactor of the helper/ducking pipeline | too broad without a reproducible runtime failure locally
Rejected: Leaving the open Tahoe stability fixes unmerged locally | keeps known aggregate/shutdown regressions in the user build
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Treat this as a Tahoe stability lane, not a complete fix for FaceTime/browser ducking; validate runtime capture separately on the target machine
Tested: xcodebuild build (Background Music Device, Background Music, BGMXPCHelper)
Tested: xcodebuild test -only-testing:BGMDriverTests
Tested: xcodebuild test -only-testing:BGMAppUnitTests
Not-tested: Privileged install of BGMXPCHelper/driver via launchd
Not-tested: Real FaceTime + browser YouTube runtime on macOS Tahoe 26.3.1
Related: upstream PR kyleneideck#849
Related: upstream PR kyleneideck#850
Tahoe stability fixes got the app building and routing again, but the user-facing goal still broke down when browser audio came from helper/XPC bundle IDs that were not grouped with the main browser app.

Expand Background Music's responsible bundle-ID mapping for Safari's modern WebContent variant and for Chromium-family renderer/plugin helpers so the main app slider can reach the processes that actually emit YouTube audio. Add unit coverage for the new bundle-ID mappings to keep the workaround from regressing.

Constraint: Tahoe removed the user-facing ducking controls and modern browser audio often originates from helper bundle IDs instead of the main app bundle
Rejected: Proc/path name scanning in the app controller | upstream already reverted a similar broad approach and the bundle-ID map is narrower and safer
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Prefer exact responsible bundle-ID mappings over broad helper process scans unless live Tahoe evidence shows the mapping is still insufficient
Tested: Background Music build; Background Music Device build; BGMXPCHelper build; BGMAppUnitTests; BGMDriverTests
Not-tested: Live FaceTime + Safari/Chrome call on Tahoe 26.3.1; privileged install/helper bootstrap with sudo-required installation
Tahoe is increasingly rejecting the locally built app/helper when Xcode's default "Sign to Run Locally" ad hoc signature is left in place. build_and_install.sh now detects a usable Apple/macOS signing identity, re-signs the installed app, driver and helper, and re-bootstraps the helper daemon so launchd sees the final executable with a Team ID.\n\nConstraint: Must keep build_and_install.sh working on machines without a developer certificate\nRejected: Force Xcode automatic signing | the project still asks xcodebuild for an obsolete Mac Development certificate from the CLI\nRejected: Reorder Xcode build phases | riskier project-file surgery than a post-install re-sign/reload\nConfidence: medium\nScope-risk: moderate\nReversibility: clean\nDirective: If Tahoe still hides the device after reinstall, inspect build_and_install.log for codesign and launchctl output before changing the driver/app matching logic again\nTested: bash -n build_and_install.sh\nTested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' -only-testing:BGMAppUnitTests test\nTested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music Device' -configuration Debug -destination 'platform=macOS' -only-testing:BGMDriverTests test\nTested: Manual re-sign of local build artifacts with Apple Development certificate and Team ID verification\nNot-tested: Full sudo install path after this patch\nNot-tested: Live FaceTime + Safari ducking verification after reinstall
Tahoe rejected the previous post-install re-sign step because the script invoked codesign through sudo. That made codesign run as root, which cannot use the invoking user’s Apple Development private key from the login keychain, so the driver re-sign failed before coreaudiod could ever load it.

The install script now temporarily hands the installed driver/helper bundles to the invoking user, signs the driver, helper, and app as that user, then restores root ownership before reloading launchd. This keeps the minimal post-install fix while matching how macOS keychain-backed signing actually works.

Constraint: The install path still has to keep the helper and HAL driver root-owned once signing is done
Rejected: Keep sudo codesign and pass a keychain path | root still cannot use the user’s private key cleanly here
Rejected: Force Xcode to build with a real identity for install | CLI signing remained brittle and broader in scope
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: If Tahoe still rejects the helper or driver, inspect build_and_install.log for ownership, codesign, and launchctl output before changing runtime logic
Tested: bash -n build_and_install.sh; xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' -only-testing:BGMAppUnitTests test; xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music Device' -configuration Debug -destination 'platform=macOS' -only-testing:BGMDriverTests test
Not-tested: Full sudo install on the user’s machine after this exact patch; live FaceTime + Safari ducking after reinstall
Tahoe currently exposes Safari tab playback through the WebKit GPU helper\n("Safari Graphics and Media") on this machine, so the existing Safari\nvolume slider only updated WebContent bundle IDs and left the real audio\nclient unchanged. Extending the existing responsible-bundle map keeps the\nUI simple while making the Safari slider follow the helper that now owns\nmedia playback.\n\nConstraint: Tahoe Safari can emit media through com.apple.WebKit.GPU instead of only WebContent\nRejected: Expose Safari helper processes as separate user-facing sliders | regresses the simpler one-slider Safari UX\nConfidence: high\nScope-risk: narrow\nDirective: Keep Safari helper bundle-ID coverage aligned with the live process names shown by Background Music on new macOS releases\nTested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' build\nTested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' -only-testing:BGMAppUnitTests/BGMMusicPlayersUnitTests test\nNot-tested: Manual Safari YouTube playback after reinstall on the user machine
Tahoe exposes NAVER Whale tab audio through Chromium helper processes rather than the main app bundle, so the visible Whale slider was not reaching the actual audio emitter. Extend the existing multiprocess browser mapping to include Whale's helper, renderer, and plugin bundle IDs, and lock the behavior with a regression test alongside the other Chromium-family browsers.

Constraint: Tahoe routes browser audio through helper bundles instead of the browser app bundle
Rejected: Generic runtime process scanning | broader change with higher risk than extending the existing bundle map
Confidence: high
Scope-risk: narrow
Directive: Keep Whale aligned with other Chromium-family mappings if helper bundle IDs change upstream
Tested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' build
Tested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' -only-testing:BGMAppUnitTests/BGMMusicPlayersUnitTests test
Not-tested: Manual Whale reinstall/runtime verification on the installed app
Whale still ignored the main browser slider on Tahoe because its Chromium audio helpers can run as non-NSRunningApplication processes, so the existing bundle-ID fanout never reached the live helper PID that owned playback. Fan out main-browser volume and pan changes to helper processes discovered under the browser bundle's Helpers directory, and send both the PID and the helper bundle ID so Chromium-family browsers can pick up the same slider setting as their main app.

Constraint: Whale helper audio processes may not be surfaced by NSRunningApplication even though they own playback
Rejected: Whale-only special case by process name | too narrow when the same Tahoe behavior can affect other Chromium-family browsers
Confidence: medium
Scope-risk: moderate
Directive: Keep the Chromium PID fanout list app-specific; do not apply this helper-path scan to shared WebKit bundle IDs without checking for cross-app side effects
Tested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' build
Tested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' -only-testing:BGMAppUnitTests/BGMMusicPlayersUnitTests test
Not-tested: Installed-app Whale runtime verification after build_and_install.sh on the target machine
The regression crash came from the new Chromium helper PID fanout path in BGMAppVolumesController: helper bundle IDs were passed into SetAppVolume/SetAppPanPosition without transferring ownership, but those APIs expect the same retained CFString contract as the existing main-app path. When the status-bar slider fired, the helper metadata array was torn down after the over-release and Background Music crashed on the main thread. Restore the retained bridge for helper bundle IDs so Whale helper fanout keeps the menu alive.

Constraint: The Objective-C controller already relies on SetAppVolume/SetAppPanPosition consuming a retained CFStringRef
Rejected: Revert helper PID fanout entirely | would re-break Whale volume control on Tahoe
Confidence: high
Scope-risk: narrow
Directive: Any new call into SetAppVolume or SetAppPanPosition from Objective-C must match the existing retained-bridge ownership contract
Tested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' build
Tested: xcodebuild -workspace BGM.xcworkspace -scheme 'Background Music' -configuration Debug -destination 'platform=macOS' -only-testing:BGMAppUnitTests/BGMMusicPlayersUnitTests test
Not-tested: Installed-app runtime confirmation after build_and_install.sh on the target machine
The Chromium helper PID fanout introduced for Whale was the newest risky path, and the user's current install is now failing at the stability layer before we can finish Whale support. Remove the fanout and fall back to the last menu-safe app-volume path while we recover the Tahoe audio stack and redesign Whale routing more conservatively.

Constraint: Current Tahoe install can wedge CoreAudio/HAL enumeration, so stability comes before broader helper coverage
Rejected: Keep fanout and debug only the crash site | user now reports menu/UI hangs and no reliable runtime verification path
Confidence: medium
Scope-risk: narrow
Reversibility: clean
Directive: Do not reintroduce helper PID fanout on the hot UI path without a reproducible runtime test for launch/menu stability
Tested: Background Music build; BGMMusicPlayersUnitTests
Not-tested: Reinstalled app runtime on the wedged local audio stack; Whale slider behavior after rollback
The install scripts used to force a coreaudiod restart while live browser\naudio utility processes were still holding sessions and before the\ninstalled driver/helper bundles were re-verified. On Tahoe that can\nwedge HAL enumeration, hang device probes, and spike system load.\n\nPause known browser audio session holders, refuse ad hoc or missing\nTeamIdentifier restarts unless explicitly overridden, and bound the\npost-restart probes so the scripts fail closed instead of hanging.\n\nConstraint: build_and_install.sh, pkg postinstall, and quick_install.sh each own a restart path\nConstraint: Must stay compatible with the macOS Bash 3 runtime\nRejected: Only document 'close your browser first' | leaves the hazardous path unchanged\nRejected: Kill every browser process outright | too destructive for an install script\nConfidence: medium\nScope-risk: moderate\nReversibility: clean\nDirective: Keep HAL reload fail-closed; do not remove signature or client-quiesce checks without a Tahoe regression test\nTested: bash -n build_and_install.sh\nTested: bash -n pkg/postinstall\nTested: bash -n BGMDriver/BGMDriver/quick_install.sh\nTested: Live PID detection query matched Whale audio.mojom.AudioService and WebKit GPU/WebContent\nNot-tested: Full install/restart on a clean macOS audio stack\nNot-tested: PKG installer GUI path end-to-end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant