Merge pull request #11 from makeusabrew/lib-split-cli
Split source into library and CLI targets
This commit is contained in:
+31
-1
@@ -8,7 +8,37 @@ let package = Package(
|
|||||||
platforms: [
|
platforms: [
|
||||||
.macOS("14.2")
|
.macOS("14.2")
|
||||||
],
|
],
|
||||||
|
products: [
|
||||||
|
// Library that can be imported by other packages
|
||||||
|
.library(
|
||||||
|
name: "AudioTeeCore",
|
||||||
|
targets: ["AudioTeeCore"]
|
||||||
|
),
|
||||||
|
// CLI executable
|
||||||
|
.executable(
|
||||||
|
name: "audiotee",
|
||||||
|
targets: ["AudioTeeCLI"]
|
||||||
|
)
|
||||||
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.executableTarget(name: "audiotee")
|
// Core library with all business logic
|
||||||
|
.target(
|
||||||
|
name: "AudioTeeCore",
|
||||||
|
path: "Sources/AudioTeeCore"
|
||||||
|
),
|
||||||
|
|
||||||
|
// CLI executable that uses the library
|
||||||
|
.executableTarget(
|
||||||
|
name: "AudioTeeCLI",
|
||||||
|
dependencies: ["AudioTeeCore"],
|
||||||
|
path: "Sources/AudioTeeCLI"
|
||||||
|
),
|
||||||
|
|
||||||
|
// Tests for the library
|
||||||
|
.testTarget(
|
||||||
|
name: "AudioTeeCoreTests",
|
||||||
|
dependencies: ["AudioTeeCore"],
|
||||||
|
path: "Tests/AudioTeeCoreTests"
|
||||||
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import AudioTeeCore
|
||||||
import CoreAudio
|
import CoreAudio
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import AudioTeeCore
|
||||||
import AudioToolbox
|
import AudioToolbox
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ public class AudioRecorder {
|
|||||||
private var outputHandler: AudioOutputHandler
|
private var outputHandler: AudioOutputHandler
|
||||||
private var converter: AudioFormatConverter?
|
private var converter: AudioFormatConverter?
|
||||||
|
|
||||||
init(
|
public init(
|
||||||
deviceID: AudioObjectID, outputHandler: AudioOutputHandler, convertToSampleRate: Double? = nil,
|
deviceID: AudioObjectID, outputHandler: AudioOutputHandler, convertToSampleRate: Double? = nil,
|
||||||
chunkDuration: Double = 0.2
|
chunkDuration: Double = 0.2
|
||||||
) {
|
) {
|
||||||
@@ -51,7 +51,7 @@ public class AudioRecorder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func startRecording() {
|
public func startRecording() {
|
||||||
Logger.debug("Starting audio recording")
|
Logger.debug("Starting audio recording")
|
||||||
|
|
||||||
// Log format info and send metadata for final format
|
// Log format info and send metadata for final format
|
||||||
@@ -112,7 +112,7 @@ public class AudioRecorder {
|
|||||||
return noErr
|
return noErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopRecording() {
|
public func stopRecording() {
|
||||||
processAudioBuffer()
|
processAudioBuffer()
|
||||||
outputHandler.handleStreamStop()
|
outputHandler.handleStreamStop()
|
||||||
cleanupIOProc()
|
cleanupIOProc()
|
||||||
+5
-3
@@ -3,10 +3,12 @@ import AudioToolbox
|
|||||||
import CoreAudio
|
import CoreAudio
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class AudioTapManager {
|
public class AudioTapManager {
|
||||||
private var tapID: AudioObjectID?
|
private var tapID: AudioObjectID?
|
||||||
private var deviceID: AudioObjectID?
|
private var deviceID: AudioObjectID?
|
||||||
|
|
||||||
|
public init() {}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
Logger.debug("Cleaning up audio tap manager")
|
Logger.debug("Cleaning up audio tap manager")
|
||||||
|
|
||||||
@@ -22,7 +24,7 @@ class AudioTapManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up the audio tap and aggregate device
|
/// Sets up the audio tap and aggregate device
|
||||||
func setupAudioTap(with config: TapConfiguration) throws {
|
public func setupAudioTap(with config: TapConfiguration) throws {
|
||||||
Logger.debug("Setting up audio tap manager")
|
Logger.debug("Setting up audio tap manager")
|
||||||
|
|
||||||
tapID = try createSystemAudioTap(with: config)
|
tapID = try createSystemAudioTap(with: config)
|
||||||
@@ -38,7 +40,7 @@ class AudioTapManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the aggregate device ID for recording
|
/// Returns the aggregate device ID for recording
|
||||||
func getDeviceID() -> AudioObjectID? {
|
public func getDeviceID() -> AudioObjectID? {
|
||||||
return deviceID
|
return deviceID
|
||||||
}
|
}
|
||||||
|
|
||||||
-1
@@ -6,7 +6,6 @@ public class BinaryAudioOutputHandler: AudioOutputHandler {
|
|||||||
public init(flushAfterWrite: Bool = false) {
|
public init(flushAfterWrite: Bool = false) {
|
||||||
self.flushAfterWrite = flushAfterWrite
|
self.flushAfterWrite = flushAfterWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
public func handleAudioPacket(_ packet: AudioPacket) {
|
public func handleAudioPacket(_ packet: AudioPacket) {
|
||||||
// Write raw binary audio data directly to stdout
|
// Write raw binary audio data directly to stdout
|
||||||
FileHandle.standardOutput.write(packet.data)
|
FileHandle.standardOutput.write(packet.data)
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import XCTest
|
||||||
|
@testable import AudioTeeCore
|
||||||
|
|
||||||
|
final class AudioPacketTests: XCTestCase {
|
||||||
|
func testPacketCreation() {
|
||||||
|
let timestamp = Date()
|
||||||
|
let duration = 1.0
|
||||||
|
let data = Data([0x01, 0x02, 0x03, 0x04])
|
||||||
|
|
||||||
|
let packet = AudioPacket(
|
||||||
|
timestamp: timestamp,
|
||||||
|
duration: duration,
|
||||||
|
data: data
|
||||||
|
)
|
||||||
|
|
||||||
|
XCTAssertEqual(packet.timestamp, timestamp)
|
||||||
|
XCTAssertEqual(packet.duration, duration)
|
||||||
|
XCTAssertEqual(packet.data, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPacketDataSize() {
|
||||||
|
let packet = AudioPacket(
|
||||||
|
timestamp: Date(),
|
||||||
|
duration: 0.5,
|
||||||
|
data: Data(repeating: 0xFF, count: 1024)
|
||||||
|
)
|
||||||
|
|
||||||
|
XCTAssertEqual(packet.data.count, 1024)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user