Jump to content

No module named Quartz


Recommended Posts

I am using a Python Script that someone else wrote to control the macOS Media keys for music playback.  It stopped working in Monterey 12.3 with Python deprecation even though I added support for Python as instructed.  I am not a programmer so any help is appreciated.  I get the error message "No module named Quartz" even after doing a "pip install pyobjc-framework-Quartz". Below is the code:

 

#!/usr/local/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()

Link to comment

When asking for help with a Workflow, please upload it somewhere as we can’t properly help you without access to it. I have some rough Swift code which can replace the Python, but without seeing your setup it’s hard to guide you on how to do it.

 

Also, please avoid asking the same question in multiple places at once at the same time, or at the very least let the people on both sides know so we can see what progress has been made.

Edited by vitor
Link to comment

First open you Run Script. Edit it:

  1. Change Language to /bin/zsh.
  2. Replace all code with /usr/bin/swift ./mediakeys "${1}"

Now open the Workflow’s contents in the Finder and create a new mediakeys file. Inside, put this code:

 

// Based on the code on https://stackoverflow.com/questions/11045814/emulate-media-key-press-on-mac

import Quartz

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

let supportedKeys: [String: UInt32] = ["playpause": NX_KEYTYPE_PLAY, "next": NX_KEYTYPE_NEXT, "prev": NX_KEYTYPE_PREVIOUS, "volup": NX_KEYTYPE_SOUND_UP, "voldown": NX_KEYTYPE_SOUND_DOWN]

func HIDPostAuxKey(key: UInt32) {
  func keyDown(_ 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)
  }

  keyDown(true)
  keyDown(false)
}

HIDPostAuxKey(key: supportedKeys[CommandLine.arguments[1]]!)

 

The code could get some cleanup, but it will work like your previous one.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...