问题
Is there a way to emulate key presses of the media keys (volume up/down, play, pause, prev, next) on common Apple notebooks?
How?
回答1:
That took some time and many hacks (trying around with ctypes, the IOKit native interface, Quartz and/or Cocoa). This seems like an easy solution now:
#!/usr/bin/python
import Quartz
# NSEvent.h
NSSystemDefined = 14
# hidsystem/ev_keymap.h
NX_KEYTYPE_SOUND_UP = 0
NX_KEYTYPE_SOUND_DOWN = 1
NX_KEYTYPE_PLAY = 16
NX_KEYTYPE_NEXT = 17
NX_KEYTYPE_PREVIOUS = 18
NX_KEYTYPE_FAST = 19
NX_KEYTYPE_REWIND = 20
def HIDPostAuxKey(key):
def doKey(down):
ev = Quartz.NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
NSSystemDefined, # type
(0,0), # location
0xa00 if down else 0xb00, # flags
0, # timestamp
0, # window
0, # ctx
8, # subtype
(key << 16) | ((0xa if down else 0xb) << 8), # data1
-1 # data2
)
cev = ev.CGEvent()
Quartz.CGEventPost(0, cev)
doKey(True)
doKey(False)
for _ in range(10):
HIDPostAuxKey(NX_KEYTYPE_SOUND_UP)
HIDPostAuxKey(NX_KEYTYPE_PLAY)
(While I needed this in Python for now, my question was not really Python related and of course you can easily translate that to any other language, esp. ObjC.)
回答2:
Thank you Albert for that! I expanded on your script a bit to make it an executable that could in turn be called by Quicksilver or another launcher/trigger handler.
#!/usr/bin/python
# CLI program to control the mediakeys on OS X. Used to emulate the mediakey on a keyboard with no such keys.
# Easiest used in combination with a launcher/trigger software such as Quicksilver.
# Main part taken from http://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac
# Glue to make it into cli program by Fredrik Wallner http://www.wallner.nu/fredrik/
import Quartz
import sys
# NSEvent.h
NSSystemDefined = 14
# hidsystem/ev_keymap.h
NX_KEYTYPE_SOUND_UP = 0
NX_KEYTYPE_SOUND_DOWN = 1
NX_KEYTYPE_PLAY = 16
NX_KEYTYPE_NEXT = 17
NX_KEYTYPE_PREVIOUS = 18
NX_KEYTYPE_FAST = 19
NX_KEYTYPE_REWIND = 20
supportedcmds = {'playpause': NX_KEYTYPE_PLAY, 'next': NX_KEYTYPE_NEXT, 'prev': NX_KEYTYPE_PREVIOUS, 'volup': NX_KEYTYPE_SOUND_UP, 'voldown': NX_KEYTYPE_SOUND_DOWN}
def HIDPostAuxKey(key):
def doKey(down):
ev = Quartz.NSEvent.otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_(
NSSystemDefined, # type
(0,0), # location
0xa00 if down else 0xb00, # flags
0, # timestamp
0, # window
0, # ctx
8, # subtype
(key << 16) | ((0xa if down else 0xb) << 8), # data1
-1 # data2
)
cev = ev.CGEvent()
Quartz.CGEventPost(0, cev)
doKey(True)
doKey(False)
if __name__ == "__main__":
try:
command = sys.argv[1]
assert(command in supportedcmds)
HIDPostAuxKey(supportedcmds[command])
except (IndexError, AssertionError):
print "Usage: %s command" % (sys.argv[0],)
print "\tSupported commands are %s" % supportedcmds.keys()
The script can be found at https://gist.github.com/4078034
回答3:
Swift 5 / MacOS 10.14.4 / Xcode 10.2
@IBAction func mediaPressed(_ sender: AnyObject) {
let NX_KEYTYPE_SOUND_UP: UInt32 = 0
let NX_KEYTYPE_SOUND_DOWN: UInt32 = 1
let NX_KEYTYPE_PLAY: UInt32 = 16
let NX_KEYTYPE_NEXT: UInt32 = 17
let NX_KEYTYPE_PREVIOUS: UInt32 = 18
let NX_KEYTYPE_FAST: UInt32 = 19
let NX_KEYTYPE_REWIND: UInt32 = 20
func HIDPostAuxKey(key: UInt32) {
func doKey(down: Bool) {
let flags = NSEvent.ModifierFlags(rawValue: (down ? 0xa00 : 0xb00))
let data1 = Int((key<<16) | (down ? 0xa00 : 0xb00))
let ev = NSEvent.otherEvent(with: NSEvent.EventType.systemDefined,
location: NSPoint(x:0,y:0),
modifierFlags: flags,
timestamp: 0,
windowNumber: 0,
context: nil,
subtype: 8,
data1: data1,
data2: -1
)
let cev = ev?.cgEvent
cev?.post(tap: CGEventTapLocation.cghidEventTap)
}
doKey(down: true)
doKey(down: false)
}
for _ in 1...10 {
HIDPostAuxKey(key:NX_KEYTYPE_SOUND_UP)
}
HIDPostAuxKey(key:NX_KEYTYPE_PLAY)
}
来源:https://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac