Skip to content

Better category switching #621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 61 additions & 17 deletions Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,45 @@
@_implementationOnly import LiveKitWebRTC
#endif

public class AudioEngineState: CustomDebugStringConvertible {
private let rtcState: LKRTCAudioEngineState

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 26 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineState' in scope

public var isOutputEnabled: Bool { rtcState.isOutputEnabled }
public var isOutputRunning: Bool { rtcState.isOutputRunning }
public var isInputEnabled: Bool { rtcState.isInputEnabled }
public var isInputRunning: Bool { rtcState.isInputRunning }
public var isInputMuted: Bool { rtcState.isInputMuted }
public var isLegacyMuteMode: Bool { rtcState.muteMode == .restartEngine }

init(fromRTCType rtcState: LKRTCAudioEngineState) {

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineState' in scope

Check failure on line 35 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineState' in scope
self.rtcState = rtcState
}

public var debugDescription: String {
"AudioEngineState(isOutputEnabled: \(isOutputEnabled), isOutputRunning: \(isOutputRunning), isInputEnabled: \(isInputEnabled), isInputRunning: \(isInputRunning), isInputMuted: \(isInputMuted), isLegacyMuteMode: \(isLegacyMuteMode))"
}
}

public class AudioEngineStateTransition: CustomDebugStringConvertible {
private let rtcStateTransition: LKRTCAudioEngineStateTransition

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 45 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

public var prev: AudioEngineState { AudioEngineState(fromRTCType: rtcStateTransition.prev) }
public var next: AudioEngineState { AudioEngineState(fromRTCType: rtcStateTransition.next) }

init(fromRTCType rtcStateTransition: LKRTCAudioEngineStateTransition) {

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 50 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
self.rtcStateTransition = rtcStateTransition
}

public var debugDescription: String {
"AudioEngineStateTransition(prev: \(prev), next: \(next))"
}
}

// Invoked on WebRTC's worker thread, do not block.
class AudioDeviceModuleDelegateAdapter: NSObject, LKRTCAudioDeviceModuleDelegate {
weak var audioManager: AudioManager?

func audioDeviceModule(_: LKRTCAudioDeviceModule, didReceiveSpeechActivityEvent speechActivityEvent: RTCSpeechActivityEvent) {
func audioDeviceModule(_: LKRTCAudioDeviceModule, didReceiveMutedSpeechActivityEvent speechActivityEvent: RTCSpeechActivityEvent) {
guard let audioManager else { return }
audioManager._state.onMutedSpeechActivity?(audioManager, speechActivityEvent.toLKType())
}
Expand All @@ -38,51 +72,61 @@

// Engine events

func audioDeviceModule(_: LKRTCAudioDeviceModule, didCreateEngine engine: AVAudioEngine) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, didCreateEngine engine: AVAudioEngine, stateTransition: LKRTCAudioEngineStateTransition) -> Int {

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 75 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineDidCreate(engine) ?? 0
return entryPoint?.engineDidCreate(engine, state: AudioEngineStateTransition(fromRTCType: stateTransition)) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, willEnableEngine engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, willEnableEngine engine: AVAudioEngine, stateTransition: LKRTCAudioEngineStateTransition) -> Int {

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 81 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineWillEnable(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
return entryPoint?.engineWillEnable(engine, state: AudioEngineStateTransition(fromRTCType: stateTransition)) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, willStartEngine engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, willStartEngine engine: AVAudioEngine, stateTransition: LKRTCAudioEngineStateTransition) -> Int {

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 87 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineWillStart(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
return entryPoint?.engineWillStart(engine, state: AudioEngineStateTransition(fromRTCType: stateTransition)) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, didStopEngine engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, didStopEngine engine: AVAudioEngine, stateTransition: LKRTCAudioEngineStateTransition) -> Int {

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 93 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineDidStop(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
return entryPoint?.engineDidStop(engine, state: AudioEngineStateTransition(fromRTCType: stateTransition)) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, didDisableEngine engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, didDisableEngine engine: AVAudioEngine, stateTransition: LKRTCAudioEngineStateTransition) -> Int {

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 99 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineDidDisable(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
return entryPoint?.engineDidDisable(engine, state: AudioEngineStateTransition(fromRTCType: stateTransition)) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, willReleaseEngine engine: AVAudioEngine) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, willReleaseEngine engine: AVAudioEngine, stateTransition: LKRTCAudioEngineStateTransition) -> Int {

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, tvOS Simulator,name=Apple TV)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, iOS Simulator,OS=18.1,name=iPhone 16 Pro, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, visionOS Simulator,name=Apple Vision Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, macOS)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-14, 15.4, iOS Simulator,OS=17.5,name=iPhone 15 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS, true)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-13, 14.2, iOS Simulator,OS=17.2,name=iPhone 14 Pro)

cannot find type 'LKRTCAudioEngineStateTransition' in scope

Check failure on line 105 in Sources/LiveKit/Audio/AudioDeviceModuleDelegateAdapter.swift

View workflow job for this annotation

GitHub Actions / Build & Test (macos-15, 16.2, macOS,variant=Mac Catalyst)

cannot find type 'LKRTCAudioEngineStateTransition' in scope
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineWillRelease(engine) ?? 0
return entryPoint?.engineWillRelease(engine, state: AudioEngineStateTransition(fromRTCType: stateTransition)) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, engine: AVAudioEngine, configureInputFromSource src: AVAudioNode?, toDestination dst: AVAudioNode, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, engine: AVAudioEngine, configureInputFromSource src: AVAudioNode?, toDestination dst: AVAudioNode, format: AVAudioFormat, stateTransition: LKRTCAudioEngineStateTransition, context: [AnyHashable: Any]) -> Int {
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineWillConnectInput(engine, src: src, dst: dst, format: format, context: context) ?? 0
return entryPoint?.engineWillConnectInput(engine,
src: src,
dst: dst,
format: format,
state: AudioEngineStateTransition(fromRTCType: stateTransition),
context: context) ?? 0
}

func audioDeviceModule(_: LKRTCAudioDeviceModule, engine: AVAudioEngine, configureOutputFromSource src: AVAudioNode, toDestination dst: AVAudioNode?, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int {
func audioDeviceModule(_: LKRTCAudioDeviceModule, engine: AVAudioEngine, configureOutputFromSource src: AVAudioNode, toDestination dst: AVAudioNode?, format: AVAudioFormat, stateTransition: LKRTCAudioEngineStateTransition, context: [AnyHashable: Any]) -> Int {
guard let audioManager else { return 0 }
let entryPoint = audioManager.buildEngineObserverChain()
return entryPoint?.engineWillConnectOutput(engine, src: src, dst: dst, format: format, context: context) ?? 0
return entryPoint?.engineWillConnectOutput(engine,
src: src,
dst: dst,
format: format,
state: AudioEngineStateTransition(fromRTCType: stateTransition),
context: context) ?? 0
}
}
80 changes: 56 additions & 24 deletions Sources/LiveKit/Audio/AudioEngineObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,54 +29,86 @@ public protocol AudioEngineObserver: NextInvokable, Sendable {
associatedtype Next = any AudioEngineObserver
var next: (any AudioEngineObserver)? { get set }

func engineDidCreate(_ engine: AVAudioEngine) -> Int
func engineWillEnable(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int
func engineWillStart(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int
func engineDidStop(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int
func engineDidDisable(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int
func engineWillRelease(_ engine: AVAudioEngine) -> Int
func engineDidCreate(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int
func engineWillEnable(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int
func engineWillStart(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int
func engineDidStop(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int
func engineDidDisable(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int
func engineWillRelease(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int

/// Provide custom implementation for internal AVAudioEngine's output configuration.
/// Buffers flow from `src` to `dst`. Preferred format to connect node is provided as `format`.
/// Return true if custom implementation is provided, otherwise default implementation will be used.
func engineWillConnectOutput(_ engine: AVAudioEngine, src: AVAudioNode, dst: AVAudioNode?, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int
func engineWillConnectOutput(_ engine: AVAudioEngine,
src: AVAudioNode,
dst: AVAudioNode?,
format: AVAudioFormat,
state: AudioEngineStateTransition,
context: [AnyHashable: Any]) -> Int
/// Provide custom implementation for internal AVAudioEngine's input configuration.
/// Buffers flow from `src` to `dst`. Preferred format to connect node is provided as `format`.
/// Return true if custom implementation is provided, otherwise default implementation will be used.
func engineWillConnectInput(_ engine: AVAudioEngine, src: AVAudioNode?, dst: AVAudioNode, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int
func engineWillConnectInput(_ engine: AVAudioEngine,
src: AVAudioNode?,
dst: AVAudioNode,
format: AVAudioFormat,
state: AudioEngineStateTransition,
context: [AnyHashable: Any]) -> Int
}

/// Default implementation to make it optional.
public extension AudioEngineObserver {
func engineDidCreate(_ engine: AVAudioEngine) -> Int {
next?.engineDidCreate(engine) ?? 0
func engineDidCreate(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int {
next?.engineDidCreate(engine, state: state) ?? 0
}

func engineWillEnable(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
next?.engineWillEnable(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
func engineWillEnable(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int {
next?.engineWillEnable(engine, state: state) ?? 0
}

func engineWillStart(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
next?.engineWillStart(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
func engineWillStart(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int {
next?.engineWillStart(engine, state: state) ?? 0
}

func engineDidStop(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
next?.engineDidStop(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
func engineDidStop(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int {
next?.engineDidStop(engine, state: state) ?? 0
}

func engineDidDisable(_ engine: AVAudioEngine, isPlayoutEnabled: Bool, isRecordingEnabled: Bool) -> Int {
next?.engineDidDisable(engine, isPlayoutEnabled: isPlayoutEnabled, isRecordingEnabled: isRecordingEnabled) ?? 0
func engineDidDisable(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int {
next?.engineDidDisable(engine, state: state) ?? 0
}

func engineWillRelease(_ engine: AVAudioEngine) -> Int {
next?.engineWillRelease(engine) ?? 0
func engineWillRelease(_ engine: AVAudioEngine, state: AudioEngineStateTransition) -> Int {
next?.engineWillRelease(engine, state: state) ?? 0
}

func engineWillConnectOutput(_ engine: AVAudioEngine, src: AVAudioNode, dst: AVAudioNode?, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int {
next?.engineWillConnectOutput(engine, src: src, dst: dst, format: format, context: context) ?? 0
func engineWillConnectOutput(_ engine: AVAudioEngine,
src: AVAudioNode,
dst: AVAudioNode?,
format: AVAudioFormat,
state: AudioEngineStateTransition,
context: [AnyHashable: Any]) -> Int
{
next?.engineWillConnectOutput(engine,
src: src,
dst: dst,
format: format,
state: state,
context: context) ?? 0
}

func engineWillConnectInput(_ engine: AVAudioEngine, src: AVAudioNode?, dst: AVAudioNode, format: AVAudioFormat, context: [AnyHashable: Any]) -> Int {
next?.engineWillConnectInput(engine, src: src, dst: dst, format: format, context: context) ?? 0
func engineWillConnectInput(_ engine: AVAudioEngine,
src: AVAudioNode?,
dst: AVAudioNode,
format: AVAudioFormat,
state: AudioEngineStateTransition,
context: [AnyHashable: Any]) -> Int
{
next?.engineWillConnectInput(engine,
src: src,
dst: dst,
format: format,
state: state,
context: context) ?? 0
}
}
Loading
Loading