add microphone capture and stable code signing for TCC persistence

Adds --capture-mic/--mic-output for a second, independently-captured audio
track (mic vs system, written to separate outputs to avoid interleaving
corruption). Embeds Info.plist at link time so the binary carries a stable
CFBundleIdentifier and the usage-description keys TCC requires, and adds
scripts/build-signed.sh + scripts/create-signing-identity.sh so a rebuilt
binary keeps the same signing identity instead of losing granted
permissions on every rebuild.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sttlab-tech
2026-08-09 13:10:08 +02:00
parent 56ac954369
commit 678557caf7
10 changed files with 678 additions and 9 deletions
+26 -6
View File
@@ -1,10 +1,20 @@
import AudioTeeCore
import Foundation
/// CLI-specific output handler that writes raw PCM audio to stdout
/// and lifecycle messages to stderr via the logger.
/// CLI-specific output handler that writes raw PCM audio to a file descriptor
/// (stdout by default) and lifecycle messages to stderr via the logger.
///
/// `source` tags every stderr message so a consumer running two tracks at
/// once (e.g. system audio + microphone, each on its own fd) can tell which
/// track a given metadata/lifecycle message belongs to.
class BinaryAudioOutputHandler: AudioOutputHandler {
private let fd = STDOUT_FILENO
private let fd: Int32
private let source: String
init(fd: Int32 = STDOUT_FILENO, source: String = "audio") {
self.fd = fd
self.source = source
}
func handleAudioData(_ pointer: UnsafeRawPointer, count: Int) {
var written = 0
@@ -21,14 +31,24 @@ class BinaryAudioOutputHandler: AudioOutputHandler {
}
func handleMetadata(_ metadata: AudioStreamMetadata) {
AudioTeeLogging.logger.writeMessage(.metadata, data: metadata)
let taggedMetadata = AudioStreamMetadata(
sampleRate: metadata.sampleRate,
channelsPerFrame: metadata.channelsPerFrame,
bitsPerChannel: metadata.bitsPerChannel,
isFloat: metadata.isFloat,
captureMode: source,
deviceName: metadata.deviceName,
deviceUID: metadata.deviceUID,
encoding: metadata.encoding
)
AudioTeeLogging.logger.writeMessage(.metadata, data: taggedMetadata)
}
func handleStreamStart() {
AudioTeeLogging.logger.writeMessage(.streamStart, data: Optional<String>.none)
AudioTeeLogging.logger.writeMessage(.streamStart, data: source)
}
func handleStreamStop() {
AudioTeeLogging.logger.writeMessage(.streamStop, data: Optional<String>.none)
AudioTeeLogging.logger.writeMessage(.streamStop, data: source)
}
}