Skip to content

feat: implement host-audio-orchestrator#3

Merged
cheefbird merged 33 commits intomainfrom
feature/host-audio-orchestrator
Jan 26, 2026
Merged

feat: implement host-audio-orchestrator#3
cheefbird merged 33 commits intomainfrom
feature/host-audio-orchestrator

Conversation

@cheefbird
Copy link
Owner

@cheefbird cheefbird commented Jan 20, 2026

Context

Phase 2 of AppFaders: building the host-side orchestration layer that connects the virtual audio driver to running applications. This branch implements device discovery via CAAudioHardware, app lifecycle monitoring via NSWorkspace, and an IPC bridge using custom AudioObject properties.

big problem: Integration testing shows coreaudiod blocks custom property writes with kAudioHardwareUnknownPropertyError. The 'afvc'/'afvq' property approach is NOT viable for host-driver communication. An architectural pivot to XPC or Mach ports will be required.

Changes Made

Host Components:

  • AudioOrchestrator - central @observable coordinator with tracked apps, volumes, driver connection state
  • DeviceManager - CAAudioHardware wrapper with AsyncStream for device list updates
  • AppAudioMonitor - NSWorkspace app tracking with AsyncStream events
  • DriverBridge - IPC via custom AudioObject properties (blocked by coreaudiod)
  • TrackedApp - Sendable model for running applications
  • DriverError - typed errors for driver communication

Driver-side:

  • VolumeStore - thread-safe per-app volume storage
  • Custom property handlers in VirtualDevice for 'afvc' (setVolume) and 'afvq' (getVolume)
  • AppFadersProperty enum with custom selectors

Tests:

  • VolumeStoreTests - concurrent access, default values
  • AppAudioMonitorTests - initial enumeration, duplicate handling
  • DriverBridgeTests - validation (volume range, bundleID length)

Testing Notes

  • swift test - all unit tests pass
  • Scripts/install-driver.sh - driver installs and registers successfully
  • swift run AppFaders - host connects to driver, but setVolume fails with kAudioHardwareUnknownPropertyError
  • Console.app shows no driver logs for volume commands (request never reaches driver)

Next step: Evaluate XPC service or Mach ports for IPC.

Integrate SimplyCoreAudio 4.1.0 for Core Audio device enumeration and
add AppFadersTests test target with placeholder test verifying import.
Updated tasks.md for host-audio-orchestrator to reflect completion of AppFadersProperty enum and VolumeStore implementation.
…ting

Add missing isPropertySettable handler for AppFadersProperty.setVolume so CoreAudio clients can properly query settability before IPC calls. Also fix extraneous blank lines in getPlugInPropertyDataSize.
Introduces the TrackedApp struct to represent and identify running applications within the host orchestrator. Includes a convenience initializer from NSRunningApplication and implements custom value semantics for Hashable and Equatable to handle NSImage correctly.
Implements LocalizedError for device discovery, property I/O, and volume validation cases.

Completes task 6 of the orchestrator spec.
Implements a thread-safe wrapper around SimplyCoreAudio to discover the virtual device and observe system-wide device list changes. Includes automatic observer cleanup and identification of the AppFaders driver by UID.
@cheefbird cheefbird force-pushed the feature/host-audio-orchestrator branch from 87fcc37 to 584c9d8 Compare January 20, 2026 04:28
Repository owner deleted a comment from github-actions bot Jan 20, 2026
Repository owner deleted a comment from github-actions bot Jan 20, 2026
Refactoring required for DeviceManager
…ions

Refactors DeviceManager to use a modern AsyncStream for audio device list changes instead of closures and manual lock management.

- Replaces onDeviceListChanged callback with deviceListUpdates AsyncStream.
- Removes NSLock and ThreadSafeArray as state is now managed via structured concurrency.
- Uses NotificationCenter.notifications(named:) for Swift 6.2 compliance.
- Implements [weak self] and proper task cancellation.
Uses NSWorkspace notifications to track application lifecycle and emits events via a modern AsyncStream.

- Tracks app launch and termination using structured concurrency.
- Manages thread-safe state for currently running applications.
- Filters processes by bundle identifier to ensure trackability.
- Integrates with the updated orchestrator design using Swift 6.2 patterns.
…esign

Updates the technical stack and architectural design to use CAAudioHardware by sbooth as the primary HAL wrapper.

- Swaps SimplyCoreAudio dependency for CAAudioHardware in tech.md.
- Refactors design.md architecture and component interfaces to use CAAudioHardware types.
- Adds migration tasks 9 and 10 to tasks.md for dependency replacement and DeviceManager refactoring.
- Renumbers subsequent tasks 11-17 to maintain spec consistency.
Updates Package.swift and Package.resolved to use sbooth/CAAudioHardware version 0.7.1.
Migrates the DeviceManager component from SimplyCoreAudio to CAAudioHardware, which is actually maintained.
Creates DriverBridge.swift for low-level IPC with the virtual driver.
- Handles serialization of VolumeCommand for setAppVolume.
- Uses AudioObject properties for setAppVolume and getAppVolume.
- Incorporates NSLock for thread safety of deviceID access.
- Adds null terminator to bundleID when retrieving volume to ensure C-string compatibility with the driver.
AudioOrchestrator for coordinating app state, device connection, and IPC.

Updates DeviceManager to be Sendable and refreshes spec documentation (tasks.md, design.md, requirements.md) for accuracy.
Sets up AudioOrchestrator startup, SIGINT handling, and the main execution loop via dispatchMain.
Implement unit tests for VolumeStore covering volume operations, clamping, and thread-safety using the Swift Testing framework.
Add unit tests for AppAudioMonitor and TrackedApp.

Refactor AppAudioMonitor to prevent duplicate launch events and add an internal initializer to TrackedApp for testing.
Added unit tests for DriverBridge and made DriverError Equatable.
Exposes driver's getAppVolume via public method for reading current volume levels back from the driver, complementing existing setVolume.
@cheefbird cheefbird self-assigned this Jan 26, 2026
@cheefbird cheefbird marked this pull request as ready for review January 26, 2026 09:43
@cheefbird cheefbird merged commit ade67ff into main Jan 26, 2026
6 checks passed
@cheefbird cheefbird deleted the feature/host-audio-orchestrator branch February 2, 2026 04:35
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