Skip to content

Instantly share code, notes, and snippets.

@yamaya
Forked from jeamland/shuttle.swift
Created April 27, 2017 13:50
Show Gist options
  • Select an option

  • Save yamaya/e64cc5d0fdf8c31f0dd1f2a7f775130e to your computer and use it in GitHub Desktop.

Select an option

Save yamaya/e64cc5d0fdf8c31f0dd1f2a7f775130e to your computer and use it in GitHub Desktop.

Revisions

  1. @jeamland jeamland created this gist Nov 17, 2016.
    106 changes: 106 additions & 0 deletions shuttle.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,106 @@
    import Foundation
    import IOKit
    import IOKit.hid
    import Quartz

    let ioman = IOHIDManagerCreate(kCFAllocatorDefault,
    IOOptionBits(kIOHIDOptionsTypeNone))
    let runloop : CFRunLoop = CFRunLoopGetCurrent()
    let devices = [
    kIOHIDVendorIDKey: 0x0b33,
    kIOHIDProductIDKey: 0x0020
    ] as CFDictionary

    let vendorKey = kIOHIDVendorIDKey as CFString
    let productKey = kIOHIDProductIDKey as CFString

    func generateMediaKeyEvent(key: Int32, down: Bool) -> CGEvent {
    let state : Int32 = down ? 0xa00 : 0xb00
    let data1 : Int32 = key << 16 | state

    let event = NSEvent.otherEvent(
    with: NSSystemDefined,
    location: NSPoint(x: 0, y: 0),
    modifierFlags: NSEventModifierFlags(rawValue: UInt(state)),
    timestamp: 0,
    windowNumber: 0,
    context: nil,
    subtype: 8,
    data1: Int(data1),
    data2: -1
    )

    return event!.cgEvent!
    }

    var valueCallback : IOHIDValueCallback = {
    (context, result, sender, value) in

    let element = IOHIDValueGetElement(value)
    let cookie = IOHIDElementGetCookie(element)
    let code = IOHIDValueGetIntegerValue(value)

    var event : CGEvent?

    switch cookie {
    case 7: /* Button 1 */
    print("Button 1: ", code)
    event = generateMediaKeyEvent(key: NX_KEYTYPE_SOUND_DOWN, down: code == 1)
    case 8: /* Button 2 */
    print("Button 2: ", code)
    event = generateMediaKeyEvent(key: NX_KEYTYPE_PREVIOUS, down: code == 1)
    case 9: /* Button 3 */
    print("Button 3: ", code)
    event = generateMediaKeyEvent(key: NX_KEYTYPE_PLAY, down: code == 1)
    case 10: /* Button 4 */
    print("Button 4: ", code)
    event = generateMediaKeyEvent(key: NX_KEYTYPE_NEXT, down: code == 1)
    case 11: /* Button 5 */
    print("Button 5: ", code)
    event = generateMediaKeyEvent(key: NX_KEYTYPE_SOUND_UP, down: code == 1)
    case 16: /* Jog Dial */
    print("Jog Dial: ", code)
    event = nil
    case 17: /* Wheel */
    print("Wheel : ", code)
    event = nil
    default:
    print("Unknown element")
    event = nil
    }

    if (event != nil) {
    event!.post(tap:.cgSessionEventTap)
    }
    }

    var attachCallback : IOHIDDeviceCallback = {
    (context, result, sender, device) in

    let v = IOHIDDeviceGetProperty(device, vendorKey) as! CFNumber as Int
    let p = IOHIDDeviceGetProperty(device, productKey) as! CFNumber as Int

    IOHIDDeviceOpen(device, IOOptionBits(kIOHIDOptionsTypeSeizeDevice))
    IOHIDDeviceRegisterInputValueCallback(device, valueCallback, nil)

    print(String(format: "attached: vendor %04x device %04x", v, p))
    }

    var detachCallback : IOHIDDeviceCallback = {
    (context, result, sender, device) in

    let v = IOHIDDeviceGetProperty(device, vendorKey) as! CFNumber as Int
    let p = IOHIDDeviceGetProperty(device, productKey) as! CFNumber as Int

    print(String(format: "detached: vendor %04x device %04x", v, p))
    }

    IOHIDManagerSetDeviceMatching(ioman, devices)
    IOHIDManagerRegisterDeviceMatchingCallback(ioman, attachCallback, nil)
    IOHIDManagerRegisterDeviceRemovalCallback(ioman, detachCallback, nil)

    IOHIDManagerScheduleWithRunLoop(ioman, runloop,
    CFRunLoopMode.defaultMode.rawValue)
    IOHIDManagerOpen(ioman, IOOptionBits(kIOHIDOptionsTypeNone))

    CFRunLoopRun()