Python Forum

Full Version: run different functions each time the same button is pressed?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I am using python inputs library to detect gamepad button presses.

Purpose: I want to change the listening mode of my Pioneer AV-Receiver when pressing RB on my Xbox Controller. The event is logged as 'BTN_TR' through python inputs library.

Right now when I press the button it loops through all added listening modes when I press RB once. (as expected) but that's not what I want. I want to change from one listening mode to the next each time I press RB.

So when I press RB for the first time it should switch from Auto Surround to Rock/Pop. When I press RB again it should switch to Ext.Stereo. And the third time I press RB it should switch back to Auto Surround.

This is my code right now. What do I need to change?

def main():
	while 1:
		events = get_gamepad()
		for event in events:

			lmd_query = eiscp.eISCP('192.168.0.59').raw('LMDQSTN')

			if lmd_query == 'LMD80': #autosurround 
				if event.code == 'BTN_TR':  
					eiscp.eISCP('192.168.0.59').raw('LMD06') #rockpop  
   
			if lmd_query == 'LMD06':  
				if event.code == 'BTN_TR':
					eiscp.eISCP('192.168.0.59').raw('LMD0C') #ext.stereo

			if lmd_query == 'LMD0C':  
				if event.code == 'BTN_TR':
					eiscp.eISCP('192.168.0.59').raw('LMD80')
				
if __name__ == "__main__":
	main()
Thank you for reading and if you have an idea please let me know!
Note: Untested code
This should hopefully cycle through each mode and then return to the first and start over cycling through each time RB is pressed.
import itertools


def change_sound(value):
    eiscp.eISCP('192.168.0.59').raw(f'{value}')


cycle_sound = itertools.cycle(('LMD06', 'LMD0C', 'LMD80'))


def main():
    while True:
        events = get_gamepad()
        for event in events:

            if event.code == 'BTN_TR':
                change_sound(next(cycle_sound))


if __name__ == "__main__":
    main()
Thank you so much for your solution! It is working as you described it. It cycles through each mode.

Is it also possible that it changes to the next mode without cycling?

Because it is going through each mode every time I press the button instead of just switching to the next mode.

Hopefully I was clear to describe the distinction. :)
It should only switch one mode at a time
import itertools

cycle_sound = itertools.cycle(('LMD06', 'LMD0C', 'LMD80'))

for _ in range(6):
    print('click button')
    print(next(cycle_sound))
Output:
click button LMD06 click button LMD0C click button LMD80 click button LMD06 click button LMD0C click button LMD80
Each time next(cycle_sound) is called it grabs the next item

what happens in for event in events:
is it possible that if event.code == 'BTN_TR': is true more than once

Myabe the while True: loop is too fast and needs a sleep to allow for the release of the button?
ahh, you're correct. Your code was working all along.

I just realised one button press is divided to the push and releasing of the button:

push:
BTN_TR
SYN_REPORT

release:
BTN_TR
SYN_REPORT

So if I push it down, it switches to the next mode. Upon releasing it switches again.

That was my mistake. Your code works great!
You may want something like this so it does nothing on the button release
import itertools
 
 
def change_sound(value):
    if value:
        eiscp.eISCP('192.168.0.59').raw(f'{value}')
 
 
cycle_sound = itertools.cycle(('LMD06', None, 'LMD0C', None, 'LMD80', None))
 
 
def main():
    while True:
        events = get_gamepad()
        for event in events:
 
            if event.code == 'BTN_TR':
                change_sound(next(cycle_sound))
 
 
if __name__ == "__main__":
    main()
Wow, was just about to ask you. Really clever and neat solution.

Now it's exactly as I need it.

Thank you so much for helping me out. :)