Last active
January 27, 2025 23:49
-
-
Save shoover/e3350400f758fb38891d539d13b3c730 to your computer and use it in GitHub Desktop.
Mic check
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import time | |
| from Foundation import NSObject, NSLog | |
| import objc | |
| import sys | |
| # Load CoreAudio framework | |
| objc.loadFramework('CoreAudio') | |
| # Load Audio Toolbox framework for additional audio session info | |
| objc.loadFramework('AudioToolbox') | |
| def get_mic_permissions(): | |
| # Load AVFoundation framework for permission check | |
| objc.loadFramework('AVFoundation') | |
| from AVFoundation import AVCaptureDevice, AVAuthorizationStatusAuthorized | |
| auth_status = AVCaptureDevice.authorizationStatusForMediaType_('vide') | |
| return auth_status == AVAuthorizationStatusAuthorized | |
| class AudioDeviceListener(NSObject): | |
| def init(self): | |
| self = super(AudioDeviceListener, self).init() | |
| if self is None: | |
| return None | |
| return self | |
| def get_input_devices(self): | |
| from CoreAudio import ( | |
| AudioObjectGetPropertyData, | |
| AudioObjectGetPropertyDataSize, | |
| AudioObjectPropertyScope, | |
| AudioObjectPropertyElement, | |
| kAudioObjectPropertyScopeGlobal, | |
| kAudioObjectPropertyElementMain, | |
| kAudioHardwarePropertyDevices, | |
| kAudioDevicePropertyDeviceName, | |
| kAudioDevicePropertyStreamConfiguration, | |
| kAudioDevicePropertyDeviceIsAlive, | |
| kAudioDevicePropertyDeviceIsRunning, | |
| AudioObjectID, | |
| ) | |
| # Get all audio devices | |
| property_address = objc.malloc(16, tags="rv") # Allocate memory for property address | |
| property_address.mSelector = kAudioHardwarePropertyDevices | |
| property_address.mScope = kAudioObjectPropertyScopeGlobal | |
| property_address.mElement = kAudioObjectPropertyElementElement | |
| dataSize = objc.sizeof_void_p | |
| status, dataSize = AudioObjectGetPropertyDataSize( | |
| AudioObjectID(1), | |
| property_address, | |
| 0, | |
| None, | |
| dataSize, | |
| ) | |
| if status: | |
| NSLog("Error getting devices size: %d", status) | |
| return [] | |
| num_devices = dataSize // 4 | |
| devices_array = objc.malloc(dataSize, tags="rv") | |
| status, _ = AudioObjectGetPropertyData( | |
| AudioObjectID(1), | |
| property_address, | |
| 0, | |
| None, | |
| dataSize, | |
| devices_array, | |
| ) | |
| if status: | |
| NSLog("Error getting devices: %d", status) | |
| return [] | |
| input_devices = [] | |
| devices = devices_array[:num_devices] | |
| for device in devices: | |
| # Get device name | |
| property_address.mSelector = kAudioDevicePropertyDeviceName | |
| dataSize = 128 | |
| device_name = objc.malloc(dataSize, tags="rv") | |
| status, _ = AudioObjectGetPropertyData( | |
| AudioObjectID(device), | |
| property_address, | |
| 0, | |
| None, | |
| dataSize, | |
| device_name, | |
| ) | |
| if status: | |
| continue | |
| # Check if device is an input device | |
| property_address.mSelector = kAudioDevicePropertyStreamConfiguration | |
| property_address.mScope = 1 # Input scope | |
| dataSize = objc.sizeof_void_p | |
| status, dataSize = AudioObjectGetPropertyDataSize( | |
| AudioObjectID(device), | |
| property_address, | |
| 0, | |
| None, | |
| dataSize, | |
| ) | |
| if status: | |
| continue | |
| buffer = objc.malloc(dataSize, tags="rv") | |
| status, _ = AudioObjectGetPropertyData( | |
| AudioObjectID(device), | |
| property_address, | |
| 0, | |
| None, | |
| dataSize, | |
| buffer, | |
| ) | |
| if status: | |
| continue | |
| # Check if device is running | |
| property_address.mSelector = kAudioDevicePropertyDeviceIsRunning | |
| is_running = objc.malloc(4, tags="rv") | |
| status, _ = AudioObjectGetPropertyData( | |
| AudioObjectID(device), | |
| property_address, | |
| 0, | |
| None, | |
| 4, | |
| is_running, | |
| ) | |
| if status: | |
| continue | |
| if is_running[0]: | |
| input_devices.append({ | |
| 'id': device, | |
| 'name': device_name.decode('utf-8').strip('\x00'), | |
| 'is_running': bool(is_running[0]) | |
| }) | |
| return input_devices | |
| def main(): | |
| print("Checking microphone usage...") | |
| # Check microphone permissions | |
| if not get_mic_permissions(): | |
| print("Warning: Microphone permissions not granted") | |
| print("Please grant microphone permissions in System Preferences > Security & Privacy > Privacy > Microphone") | |
| return | |
| listener = AudioDeviceListener.alloc().init() | |
| try: | |
| while True: | |
| active_devices = listener.get_input_devices() | |
| if not active_devices: | |
| print("\nNo active input devices found") | |
| else: | |
| print("\nActive input devices:") | |
| print("-" * 50) | |
| for device in active_devices: | |
| print(f"Device: {device['name']}") | |
| print(f"ID: {device['id']}") | |
| print(f"Status: {'Active' if device['is_running'] else 'Inactive'}") | |
| print("-" * 50) | |
| time.sleep(1) # Update every second | |
| except KeyboardInterrupt: | |
| print("\nMonitoring stopped") | |
| if __name__ == '__main__': | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| tell application "Microsoft Teams" | |
| activate | |
| delay 1 -- Give Teams time to come to foreground | |
| end tell | |
| -- Main logging function with generic recursion | |
| on logElement(element, indentLevel) | |
| set indent to "" | |
| repeat indentLevel times | |
| set indent to indent & " " | |
| end repeat | |
| try | |
| set elementRole to role of element | |
| on error | |
| set elementRole to "unknown role" | |
| end try | |
| try | |
| set elementName to name of element | |
| on error | |
| set elementName to "unnamed" | |
| end try | |
| -- Log basic element info | |
| log indent & "Name: " & elementName & ", Role: " & elementRole | |
| -- Try to get any additional properties that might be interesting | |
| try | |
| if value of element exists then | |
| log indent & " Value: " & value of element | |
| end if | |
| end try | |
| try | |
| if description of element exists then | |
| log indent & " Description: " & description of element | |
| end if | |
| end try | |
| try | |
| if help of element exists then | |
| log indent & " Help: " & help of element | |
| end if | |
| end try | |
| -- Generic child element recursion | |
| try | |
| -- Get all UI elements regardless of container type | |
| set childElements to UI elements of element | |
| if length of childElements is greater than 0 then | |
| repeat with childElement in childElements | |
| my logElement(childElement, indentLevel + 1) | |
| end repeat | |
| end if | |
| on error errorMessage | |
| -- Silently ignore errors for elements that can't have children | |
| end try | |
| end logElement | |
| tell application "System Events" | |
| tell process "Microsoft Teams" | |
| -- Log process info | |
| log "=== Starting UI Element Logging for Microsoft Teams ===" | |
| log "Process name: " & name | |
| -- Get and log info for all windows | |
| try | |
| set windowList to windows | |
| log "Number of windows: " & (count of windowList) | |
| repeat with windowIndex from 1 to count of windowList | |
| set currentWindow to item windowIndex of windowList | |
| -- Log window info | |
| log "=== Window " & windowIndex & " ===" | |
| log "Window name: " & name of currentWindow | |
| try | |
| log "Window size: " & size of currentWindow | |
| log "Window position: " & position of currentWindow | |
| end try | |
| -- Log all elements in the window | |
| try | |
| set topLevelElements to UI elements of currentWindow | |
| repeat with element in topLevelElements | |
| my logElement(element, 1) | |
| end repeat | |
| on error windowElementError | |
| log "Error accessing elements in window " & windowIndex & ": " & windowElementError | |
| end try | |
| log "=== End of Window " & windowIndex & " ===" | |
| end repeat | |
| on error windowError | |
| log "Error accessing windows: " & windowError | |
| end try | |
| log "=== UI Element Logging Complete ===" | |
| end tell | |
| end tell |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pip install pyobjc-framework-CoreAudio pyobjc-framework-AudioToolbox pyobjc-framework-AVFoundation |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment