Skip to content

Instantly share code, notes, and snippets.

@dnicolson
Last active September 16, 2020 21:22
Show Gist options
  • Save dnicolson/d88963a7d50fd7fa11220d27c7b65d08 to your computer and use it in GitHub Desktop.
Save dnicolson/d88963a7d50fd7fa11220d27c7b65d08 to your computer and use it in GitHub Desktop.
Play/pause iTunes by double tapping the fn key
// clang -framework IOKit -framework Carbon itunes_pp.c -o itunes_pp && ./itunes_pp
#include <sys/time.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDValue.h>
CFMutableDictionaryRef CreateMatchingDictionary(UInt32 usage_page, UInt32 usage)
{
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFNumberRef page_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page);
CFDictionarySetValue(dictionary, CFSTR(kIOHIDDeviceUsagePageKey), page_number);
CFRelease(page_number);
CFNumberRef usage_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
CFDictionarySetValue(dictionary, CFSTR(kIOHIDDeviceUsageKey), usage_number);
CFRelease(usage_number);
return dictionary;
}
void HIDKeyboardCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value)
{
IOHIDElementRef elem = IOHIDValueGetElement(value);
uint32_t usage_page = IOHIDElementGetUsagePage(elem);
uint32_t usage = IOHIDElementGetUsage(elem);
long pressed = IOHIDValueGetIntegerValue(value);
static long last_pressed;
if (usage_page == 0xFF && usage == 3 && pressed == 0) {
struct timeval time;
gettimeofday(&time, NULL);
long microtime = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
if (last_pressed) {
long diff = microtime - last_pressed;
if (diff < 500000) {
system("osascript -l JavaScript -e 'Application(\"iTunes\").playpause()'");
}
}
last_pressed = microtime;
}
}
int main()
{
IOHIDManagerRef hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
CFMutableDictionaryRef matching_dictionary = CreateMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
IOHIDManagerSetDeviceMatching(hid_manager, matching_dictionary);
IOHIDManagerRegisterInputValueCallback(hid_manager, HIDKeyboardCallback, NULL);
IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
CFRunLoopRun();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment