oficina / meet Public

Clone
git clone https://amadan.net/oficina/meet

Plain git — no account needed to clone.

Download

Download this file

1#if os(macOS)
2 import CoreAudio
3 import LiveKitWebRTC
4 import XCTest
5 @testable import CallsKit
6
7 /// Paul's first-launch report, reproduced without a Scarlett: a public
8 /// aggregate device stands in for an interface that is connected but is
9 /// not the system default, and is remembered as the microphone. Opt-in
10 /// (CALLS_AUDIO_REPRO=1) because it adds a device to the Mac for the
11 /// length of the test.
12 final class ScarlettReproTests: XCTestCase {
13 @MainActor func testARememberedNonDefaultInterfaceIsUsedAtFirstLaunch() throws {
14 guard ProcessInfo.processInfo.environment["CALLS_AUDIO_REPRO"] == "1" else {
15 throw XCTSkip("set CALLS_AUDIO_REPRO=1 to add a stand-in interface to this Mac")
16 }
17 let inventory = CoreAudioDevices.inventory()
18 guard let mic = inventory.defaultInput, let speaker = inventory.defaultOutput else {
19 throw XCTSkip("no default devices")
20 }
21 let uid = "net.amadan.oficina.calls.repro.\(UUID().uuidString)"
22 let description: [String: Any] = [
23 kAudioAggregateDeviceNameKey: "Stand-in Scarlett", kAudioAggregateDeviceUIDKey: uid,
24 kAudioAggregateDeviceMainSubDeviceKey: speaker,
25 kAudioAggregateDeviceSubDeviceListKey: [
26 [kAudioSubDeviceUIDKey: mic, kAudioSubDeviceDriftCompensationKey: 1], [kAudioSubDeviceUIDKey: speaker],
27 ],
28 ]
29 var device = AudioDeviceID(0)
30 XCTAssertEqual(AudioHardwareCreateAggregateDevice(description as CFDictionary, &device), noErr)
31 defer { AudioHardwareDestroyAggregateDevice(device) }
32 RunLoop.main.run(until: Date().addingTimeInterval(0.5))
33
34 let suite = "calls-repro-\(UUID().uuidString)"
35 let store = UserDefaults(suiteName: suite)!
36 defer { store.removePersistentDomain(forName: suite) }
37 store.set(uid, forKey: "audioInputUID")
38 store.set("Stand-in Scarlett", forKey: "audioInputName")
39
40 let routes = AudioRoutes(defaults: store)
41 let audio = CallAudio(routes: routes, audioDevice: nil)
42 print("REPRO at launch: input \(routes.currentInput ?? "nil"), note \"\(routes.routeNote)\"")
43 XCTAssertEqual(routes.currentInput, uid, "the remembered interface at launch")
44 XCTAssertEqual(routes.routeNote, "")
45
46 let pc = audio.factory.peerConnection(
47 with: RTCConfiguration(),
48 constraints: RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil), delegate: nil)
49 defer { pc?.close() }
50 let listed = audio.factory.audioDeviceModule.inputDevices.map(\.deviceId)
51 print("REPRO engine module inputs after the first connection: \(listed)")
52 routes.refresh()
53 XCTAssertEqual(routes.currentInput, uid, "and after the first connection")
54 XCTAssertEqual(routes.routeNote, "")
55 }
56 }
57#endif
58