Command: Monitor Streams
Relevant source files
The following files were used as context for generating this wiki page:
The monitor command manages multi-output aggregate devices to facilitate system audio loopback and monitoring. It allows the system to route audio to both a physical output and a virtual loopback device like BlackHole simultaneously. This capability is essential for capturing system audio while maintaining the user's ability to hear the output.
Sources: Sources/Spike/MonitorCmd.swift:6-10, README.md:9-13
Architecture and Core Components
The system relies on the CoreAudio Hardware Abstraction Layer (HAL) to create and manage aggregate devices. The MonitorCmd struct serves as the entry point for subcommands, while MonitorDevice handles the low-level CoreAudio interactions.
Component Breakdown
| Component | Description |
|---|---|
MonitorCmd | Processes subcommands (status, setup, teardown) and manages state persistence. |
MonitorDevice | Creates and destroys the "kilde Monitor" aggregate device using CoreAudio. |
AudioHAL | Provides utility methods to query existing system audio devices and their properties. |
State | A JSON-serializable structure that stores the original default output UID for restoration. |
Sources: Sources/Spike/MonitorCmd.swift:13-25, Sources/Spike/AggregateDevice.swift:6-9, Sources/Spike/AudioDevices.swift:30-35
Operations and Data Flow
The command supports three primary operations to manage the audio monitoring environment.
Setup Process
When you run spike monitor setup, the system creates a "stacked" aggregate device. This device combines the current default output with a BlackHole virtual device. The system then sets this new aggregate device as the system's default output.
The diagram shows the sequence of checks and operations required to establish the monitoring loopback.
Sources: Sources/Spike/MonitorCmd.swift:44-65, Sources/Spike/AggregateDevice.swift:13-30
Teardown and Restoration
The teardown command restores the system to its original state. It reads the saved state file, reverts the default output to the original device, and destroys the aggregate device.
This sequence ensures that the user's audio configuration is restored exactly as it was before the setup.
Sources: Sources/Spike/MonitorCmd.swift:67-80, Sources/Spike/AggregateDevice.swift:33-36
Device Configuration Details
The aggregate device uses specific CoreAudio keys to ensure simultaneous output. The stacked flag is particularly critical as it mimics the "Multi-Output Device" behavior found in macOS Audio MIDI Setup.
let desc: [String: Any] = [
kAudioAggregateDeviceNameKey: name,
kAudioAggregateDeviceUIDKey: uid,
kAudioAggregateDeviceIsPrivateKey: false,
"stacked": true,
kAudioAggregateDeviceSubDeviceListKey: memberUIDs.map { [kAudioSubDeviceUIDKey: $0] },
kAudioAggregateDeviceMasterSubDeviceKey: masterUID,
]
Sources: Sources/Spike/AggregateDevice.swift:16-25
Verification and Status
The status subcommand lists all audio devices and identifies the current roles (Default Output, BlackHole, or kilde Monitor).
- Status Indicators: The output marks devices with
←既定出力,←BlackHole, or←kilde Monitor. - Presence Check: It explicitly reports if
kilde Monitor existsviaMonitorDevice.exists.
Sources: Sources/Spike/MonitorCmd.swift:27-42, Sources/Spike/AudioDevices.swift:8-25
Integration with Recording
The monitoring setup is verified through integration tests that combine monitor setup with rec-device. This confirms that audio played to the aggregate device correctly loops back through the BlackHole interface for recording.
Sources: scripts/integration-test.sh:176-193, Sources/Spike/RecDeviceCmd.swift:13-25
The monitor command provides a stable environment for system audio capture by automating the complex task of managing CoreAudio aggregate devices and maintaining system state for safe restoration.