//go:build darwin package permissions /* #cgo CFLAGS: -x objective-c #cgo LDFLAGS: -framework ApplicationServices -framework AVFoundation #include #import static int accessibilityGranted(void) { return AXIsProcessTrusted() ? 1 : 0; } static void requestAccessibility(void) { NSDictionary* opts = @{(__bridge NSString*)kAXTrustedCheckOptionPrompt: @YES}; AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts); } static int inputMonitoringGranted(void) { return CGPreflightListenEventAccess() ? 1 : 0; } static void requestInputMonitoring(void) { CGRequestListenEventAccess(); } static int microphoneStatus(void) { return (int)[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; } static int requestMicrophone(void) { __block int granted = 0; dispatch_semaphore_t sem = dispatch_semaphore_create(0); [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL ok) { granted = ok ? 1 : 0; dispatch_semaphore_signal(sem); }]; dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC)); return granted; } */ import "C" import "os/exec" // Statuses returns the current macOS privacy permission state. func Statuses() []Status { return []Status{ { ID: IDMicrophone, Granted: C.microphoneStatus() == 3, State: microphoneState(int(C.microphoneStatus())), Required: true, }, { ID: IDAccessibility, Granted: C.accessibilityGranted() != 0, State: grantedState(C.accessibilityGranted() != 0), Required: true, }, { ID: IDInputMonitoring, Granted: C.inputMonitoringGranted() != 0, State: grantedState(C.inputMonitoringGranted() != 0), Required: true, }, } } // Request asks macOS for a permission where a public prompt API exists, // then opens the matching System Settings pane. func Request(id string) { switch id { case IDMicrophone: C.requestMicrophone() openSettings(id) case IDAccessibility: C.requestAccessibility() openSettings(id) case IDInputMonitoring: C.requestInputMonitoring() openSettings(id) } } func OpenSettings(id string) { openSettings(id) } func microphoneState(status int) string { switch status { case 0: return "notDetermined" case 1: return "restricted" case 2: return "denied" case 3: return "granted" default: return "unknown" } } func grantedState(granted bool) string { if granted { return "granted" } return "denied" } func openSettings(id string) { url := "x-apple.systempreferences:com.apple.preference.security" switch id { case IDMicrophone: url = "x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone" case IDAccessibility: url = "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility" case IDInputMonitoring: url = "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent" } _ = exec.Command("open", url).Start() }