@@ -41,59 +41,42 @@ private func mapAudioApplicationPermission(_ permission: AVAudioApplication.reco
4141 }
4242}
4343
44- private func currentMicrophonePermissionStatus( ) -> Int {
45- let captureStatus = mapCaptureMicrophoneStatus ( AVCaptureDevice . authorizationStatus ( for: . audio) )
46-
47- if #available( macOS 14 . 0 , * ) {
48- let appStatus = mapAudioApplicationPermission ( AVAudioApplication . shared. recordPermission)
44+ private func captureMicrophonePermissionStatus( ) -> Int {
45+ mapCaptureMicrophoneStatus ( AVCaptureDevice . authorizationStatus ( for: . audio) )
46+ }
4947
50- if appStatus == grantedValue || captureStatus == grantedValue {
51- return grantedValue
52- }
48+ private func combinedMicrophonePermissionStatus( appStatus: Int , captureStatus: Int ) -> Int {
49+ if appStatus == grantedValue || captureStatus == grantedValue {
50+ return grantedValue
51+ }
5352
54- if appStatus == neverRequestedValue || captureStatus == neverRequestedValue {
55- return neverRequestedValue
56- }
53+ if appStatus == errorValue {
54+ return captureStatus
55+ }
5756
58- return appStatus == errorValue ? captureStatus : appStatus
57+ if captureStatus == errorValue {
58+ return appStatus
5959 }
6060
61- return captureStatus
62- }
61+ if appStatus == deniedValue || captureStatus == deniedValue {
62+ return deniedValue
63+ }
6364
64- @_cdecl ( " _microphone_permission_status " )
65- public func _microphone_permission_status( ) -> Int {
66- currentMicrophonePermissionStatus ( )
65+ return neverRequestedValue
6766}
6867
69- @_cdecl ( " _request_microphone_permission " )
70- public func _request_microphone_permission( ) -> Bool {
71- if currentMicrophonePermissionStatus ( ) == grantedValue {
72- return true
73- }
68+ private func currentMicrophonePermissionStatus( ) -> Int {
69+ let captureStatus = captureMicrophonePermissionStatus ( )
7470
7571 if #available( macOS 14 . 0 , * ) {
76- switch AVAudioApplication . shared. recordPermission {
77- case . granted:
78- return true
79- case . denied:
80- return currentMicrophonePermissionStatus ( ) == grantedValue
81- case . undetermined:
82- let semaphore = DispatchSemaphore ( value: 0 )
83- var granted = false
84-
85- AVAudioApplication . requestRecordPermission { allowed in
86- granted = allowed
87- semaphore. signal ( )
88- }
89-
90- _ = semaphore. wait ( timeout: . now( ) + . seconds( 60 ) )
91- return granted || currentMicrophonePermissionStatus ( ) == grantedValue
92- @unknown default :
93- return currentMicrophonePermissionStatus ( ) == grantedValue
94- }
72+ let appStatus = mapAudioApplicationPermission ( AVAudioApplication . shared. recordPermission)
73+ return combinedMicrophonePermissionStatus ( appStatus: appStatus, captureStatus: captureStatus)
9574 }
9675
76+ return captureStatus
77+ }
78+
79+ private func requestCaptureMicrophonePermission( ) -> Bool {
9780 let status = AVCaptureDevice . authorizationStatus ( for: . audio)
9881
9982 switch status {
@@ -117,6 +100,58 @@ public func _request_microphone_permission() -> Bool {
117100 }
118101}
119102
103+ @available ( macOS 14 . 0 , * )
104+ private func requestAppMicrophonePermission( ) -> Bool {
105+ switch AVAudioApplication . shared. recordPermission {
106+ case . granted:
107+ return true
108+ case . denied:
109+ return false
110+ case . undetermined:
111+ let semaphore = DispatchSemaphore ( value: 0 )
112+ var granted = false
113+
114+ AVAudioApplication . requestRecordPermission { allowed in
115+ granted = allowed
116+ semaphore. signal ( )
117+ }
118+
119+ _ = semaphore. wait ( timeout: . now( ) + . seconds( 60 ) )
120+ return granted
121+ @unknown default :
122+ return false
123+ }
124+ }
125+
126+ @_cdecl ( " _microphone_permission_status " )
127+ public func _microphone_permission_status( ) -> Int {
128+ currentMicrophonePermissionStatus ( )
129+ }
130+
131+ @_cdecl ( " _request_microphone_permission " )
132+ public func _request_microphone_permission( ) -> Bool {
133+ if currentMicrophonePermissionStatus ( ) == grantedValue {
134+ return true
135+ }
136+
137+ if #available( macOS 14 . 0 , * ) {
138+ let appStatus = mapAudioApplicationPermission ( AVAudioApplication . shared. recordPermission)
139+ if appStatus == neverRequestedValue && requestAppMicrophonePermission ( ) {
140+ return true
141+ }
142+
143+ if currentMicrophonePermissionStatus ( ) == grantedValue {
144+ return true
145+ }
146+ }
147+
148+ if requestCaptureMicrophonePermission ( ) {
149+ return true
150+ }
151+
152+ return currentMicrophonePermissionStatus ( ) == grantedValue
153+ }
154+
120155@_cdecl ( " _audio_capture_permission_status " )
121156public func _audio_capture_permission_status( ) -> Int {
122157 guard let tccHandle,
0 commit comments