Search code examples
pythonpyautoguimacos-high-sierra

Trying to mute the system using pyautogui.press('volumemute') but it's not doing anything


Simple code, does not work, is there anything else I need to do? This is just a test, I just want to know if 'volumemute' works or not, other special keys like 'capslock', and 'volumeup' do not work as well. What is 'volumemute' doing? is it muting the system? was hoping to see mac's little volume window, but it also does not mute, say, a youtube video on firefox...

import pyautogui
import time

confirm_window = pyautogui.alert()
if confirm_window == 'OK':
    time.sleep(1)
    pyautogui.press('volumemute')       # Does not work
    pyautogui.press('a')                # Does work
    pyautogui.press('b')                # Does work

I have tried the solution on this link, If I copy either Phylliida's solution or kenorb's solution on a new file and call KeyPress() of the same examples, the same result happens.

I also saw on pyautogui's github page that there is a permission issue with mojave, and even though it should not affect me I added PyCharm, Python Launcher and Terminal to the list in Accessibility, image, I want to be able to lower the volume in my script when I press a button that performs other actions as well, like moving the cursor to a specific coordinate etc. Also, Macbook early 2011, high sierra is as far as I can upgrade de OS

Many thanks


Solution

  • Ah well, that took a bit to figure out. :-)

    Finding the bug:

    Turns out that one of the many issues with pyautogui is this one from 2015 complaining that press is not working for all keys in macOS, which already has a partial (!!) solution proposed in pull #213. In this specific case, the original code is using two consecutive if … statements instead of if … elif … which makes the code break.

    If you examine the code on GitHub, you'll find that the .press() method is defined in init.py to refer to the platform-dependent _keyup() and _keydown() function calls defined here for macOS. If you manually apply the fix from pull #213, you'll still have to fix another thing, however:

    Pyautogui uses (both in _keyup() as well in _keydown()) the line:

    if key in special_key_translate_table:
    

    but before this line is executed, "key" has already been transformed to lowercase due this line in init.py:

    if len(key) > 1:
        key = key.lower()
    

    The dictionary for special_key_translate_table defined here however expects uppercase keys like "KEYTYPE_MUTE" so the lookup won't work!

    Fixing the code:

    First, figure out where the pyautogui code lives on your installation (i.e. figure out where the site-packages are installed). The easiest way to do this is run this code:

    from pyautogui import press
    press()
    

    which should throw an error message like this:

    Traceback (most recent call last):
      File "pyautogui_test_2.py", line 6, in <module>
        press()
      File "/path/to/the/python/site-packages/pyautogui/__init__.py", line 586, in wrapper
        returnVal = wrappedFunction(*args, **kwargs)
    TypeError: press() missing 1 required positional argument: 'keys'
    

    Note that the path within the Traceback is dependent on your installation, and now go and open the pyautogui folder within your site-packages (i.e. "/path/to/the/python/site-packages/pyautogui/") and therein edit the file "_pyautogui_osx.py" near line 219 to this:

    def _keyDown(key):
        if key.upper() in special_key_translate_table:
            _specialKeyEvent(key.upper(), 'down')
        elif key not in keyboardMapping or keyboardMapping[key] is None:
            return    
        else:
            _normalKeyEvent(key, 'down')
    
    def _keyUp(key):
        if key.upper() in special_key_translate_table:
            _specialKeyEvent(key.upper(), 'up')
        elif key not in keyboardMapping or keyboardMapping[key] is None:
            return
        else:
            _normalKeyEvent(key, 'up')
    

    which contains both the fix from pull #213 mentioned above, as well as a corrected lookup function using key.upper(). Now you should be able to use all the keys from the aforementioned special_key_translate_table dictionary to e.g. mute the system volume by calling press(u'KEYTYPE_MUTE') in your scripts.

    Note that all special keycodes are also defined on Apple's opensource documentation for the Human Interface system.