I recently coded an extension to quodlibet capturing multimedia keys (since the codlibet itself is absorbed); the same process applies to your installation.
I used the CGEventTapCreate hook quartz and the event loop and Cocoa AppKit framework to decrypt the key codes for this.
The following code registers a python callback that is passed by global keystroke and fires an event loop:
import Quartz from AppKit import NSKeyUp, NSSystemDefined, NSEvent # Set up a tap, with type of tap, location, options and event mask tap = Quartz.CGEventTapCreate( Quartz.kCGSessionEventTap, # Session level is enough for our needs Quartz.kCGHeadInsertEventTap, # Insert wherever, we do not filter Quartz.kCGEventTapOptionListenOnly, # Listening is enough Quartz.CGEventMaskBit(NSSystemDefined), # NSSystemDefined for media keys keyboardTapCallback, None ) runLoopSource = Quartz.CFMachPortCreateRunLoopSource(None, tap, 0) Quartz.CFRunLoopAddSource( Quartz.CFRunLoopGetCurrent(), runLoopSource, Quartz.kCFRunLoopDefaultMode ) # Enable the tap Quartz.CGEventTapEnable(tap, True) # and run! This won't return until we exit or are terminated. Quartz.CFRunLoopRun()
I defined a tap only for system keys (media keys); you need to specify a different event mask ( CGEventMaskBit with one or more Event Types ); e.g. Quartz.CGEventMaskBit(Quartz.kCGEventKeyUp) for key events.
The callback must have the following signature (it implements the CGEventTapCallBack method from the Quartz API :
def keyboardTapCallback(proxy, type_, event, refcon):
I converted the Quartz event to NSEvent , because all the information I could find in the Mac multimedia keys referred to this class.
Basically, you can also achieve the same with the AppKit API, but then your Python application is seen as a Mac application (visible in the Dock with an icon and everything), while I wanted it to be saved in the background in whole.