Skip to content

Instantly share code, notes, and snippets.

@fredrikw
Created November 15, 2012 11:07
Show Gist options
  • Save fredrikw/4078034 to your computer and use it in GitHub Desktop.
Save fredrikw/4078034 to your computer and use it in GitHub Desktop.
Python script 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.
#!/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()
@fredrikw
Copy link
Author

Since the script is >10 years I am not surprised that it doesn't work and I don't remember if there was something special needed.

However, the error you get is a bit puzzling. If you do not get any error messages on the pip install part I guess that the pip you get is not the version corresponding to the python path in the "dashbing" (i.e. /usr/bin/python). You could try to run /usr/bin/python -m pip install pyobjc-framework-Quartz instead and see if you have better luck then.

@mikedvzo
Copy link

mikedvzo commented Mar 23, 2022

Looks like you are correct but since 12.3 deprecated Python it is now installed in /usr/local/bin/python but when I run the command "/usr/local/bin/python -m pip install pyobjc-framework-Quartz" I got an error instead of saying already installed. I also tried: /Users/divincem/.pyenv/versions/2.7.18/bin/python2.7 -m pip install pyobjc-framework-Quartz" to the real path with the same error. Looks liek PIP does not support Python 2.7 if I am reading correctly.

DIVINCEM-mac:bin > /Users/divincem/.pyenv/versions/2.7.18/bin/python2.7 -m pip install pyobjc-framework-Quartz
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting pyobjc-framework-Quartz
Using cached https://files.pythonhosted.org/packages/ce/e3/be5dd50240fe90d597c2afabc3cd27304ba5bfc66354f5fa52b0fa5bfe09/pyobjc-framework-Quartz-5.3.tar.gz
ERROR: Command errored out with exit status 1:
command: /Users/divincem/.pyenv/versions/2.7.18/bin/python2.7 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/2d/pvf3w0y12p968b3vlv0dx_jc0000gp/T/pip-install-4TWtam/pyobjc-framework-Quartz/setup.py'"'"'; file='"'"'/private/var/folders/2d/pvf3w0y12p968b3vlv0dx_jc0000gp/T/pip-install-4TWtam/pyobjc-framework-Quartz/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base pip-egg-info
cwd: /private/var/folders/2d/pvf3w0y12p968b3vlv0dx_jc0000gp/T/pip-install-4TWtam/pyobjc-framework-Quartz/
Complete output (7 lines):
Traceback (most recent call last):
File "", line 1, in
File "/private/var/folders/2d/pvf3w0y12p968b3vlv0dx_jc0000gp/T/pip-install-4TWtam/pyobjc-framework-Quartz/setup.py", line 61, in
[ 'Modules/_CVPixelBuffer.m' ]),
File "pyobjc_setup.py", line 408, in Extension
cflags.append("-DPyObjC_BUILD_RELEASE=%02d%02d"%(tuple(map(int, os.path.basename(data)[6:-4].split('.')))))
ValueError: invalid literal for int() with base 10: ''
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
WARNING: You are using pip version 19.2.3, however version 20.3.4 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

@fredrikw
Copy link
Author

So then probably change the first line to
#!/usr/local/bin/python
That should probably work looking at your result from /usr/local/bin/python -m pip install pyobjc-framework-Quartz
Python 2.7 should be avoided by now

@mikedvzo
Copy link

I had tried that before expanding the command and got the same result. Someone on the Alfred Forum converted it to Swift for me 🙂

@Alexandro1112
Copy link

Hello there, I working on Mac OS Catalina 10.15.7, when I installed Quartz I got warning:

Cannot find reference 'CGEventPost' in '__init__.py | __init__.py'

How to solve them?

@fredrikw
Copy link
Author

As I said above, this script is really dated so I don't remember and I don't use it any longer either. So I'm afraid I cannot help much. Did you really get the error when you installed Quartz?

@Alexandro1112
Copy link

I already installed quartz.However your code is working, despite the error.

@Alexandro1112
Copy link

And I want to ask you, where did you find Quartz documentation? I have seen the official Quartz documentation but have not found an explanation for it methods this framework.

@fredrikw
Copy link
Author

I just copied the main thing from the StackOverflow answer that is linked in the top comment of the script. My only contribution was adding the CLI.

@aleksandersumowski
Copy link

I've updated the script for python 3 and worked out the correct egg to install:
https://gist.github.com/aleksandersumowski/a296a910fd3c6722744a2c3b0a1b5bf5

the script assumes python 3 installed via homebrew on a M* computer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment