Search code examples
pythonpython-3.xbooleankeypressosc

How can I have a keypress do one thing the first time, and a different thing the second time?


So I've put this script together, which allows me to send an osc, (open sound control), message whenever I hit the "w" key. (I need this to run in the background of my computer so any suggestions on how to make it more efficient would be appreciated!! :D)

The problem I've come to, is that I want it to send a different message when I hit "w" for the second time. (That's where the client.send_message comes in.) You'll see that I began to write this, to no avail lol.

In a nutshell, when I hit "w" the first time, it works perfectly. (Executes client.send_message("/TABS", "Mixer")). Now when I hit it the second time, I want it to execute client.send_message("/TABS", "Instruments") How can I go about doing this?

Code:

import argparse
import pynput

from pythonosc import udp_client
from pynput.keyboard import Key, Listener
from pynput import keyboard
import keyboard

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", default="192.168.1.140",
        help="The ip of the OSC server")
    parser.add_argument("--port", type=int, default=8420,
        help="The port the OSC server is listening on")
    args = parser.parse_args()

    client = udp_client.SimpleUDPClient(args.ip, args.port)

    def on_press(key):
        if keyboard.is_pressed('w'):
            client.send_message("/TABS", "Mixer")
        else:
            client.send_message("/TABS", "Instruments")


    with Listener(on_press=on_press) as listener:
        listener.join()

Solution

  • Since you want to cycle the two operations back and forth, you can use itertools.cycle to do exactly that.

    First, you'll want to define two small functions to do your two operations. In this case, I'm sending client as an argument to the functions.

    def do_mixer(client_arg):
        client_arg.send_message("/TABS", "Mixer")
    
    def do_instruments(client_arg):
        client_arg.send_message("/TABS", "Instruments")
    

    Then, you can create a cycle object to endlessly switch between the two functions with each press to "w":

    import argparse
    import pynput
    
    from pythonosc import udp_client
    from pynput.keyboard import Key, Listener
    from pynput import keyboard
    import keyboard
    
    # Additional import
    from itertools import cycle
    
    # New funcs
    def do_mixer(client_arg):
        client_arg.send_message("/TABS", "Mixer")
    
    def do_instruments(client_arg):
        client_arg.send_message("/TABS", "Instruments")
    
    if __name__ == "__main__":
        parser = argparse.ArgumentParser()
        parser.add_argument("--ip", default="192.168.1.140",
            help="The ip of the OSC server")
        parser.add_argument("--port", type=int, default=8420,
            help="The port the OSC server is listening on")
        args = parser.parse_args()
    
        client = udp_client.SimpleUDPClient(args.ip, args.port)
    
        # Function cycler
        func_cycler = cycle((do_mixer, do_instruments))
    
        def on_press(key):
            if keyboard.is_pressed('w'):
                # With each press of "w", call the function that is next in line
                # The cycle object will iterate the collection given to it infinitely
                # In this case, it will be: do_mixer, do_instruments, do_mixer, ...
                next(func_cycler)(client)
    
        with Listener(on_press=on_press) as listener:
            listener.join()