RPi-Jukebox-RFID
RPi-Jukebox-RFID copied to clipboard
π | Play when button is pressed and pause when button is released
Similar to #1146, I'm trying to get a gpio button to play the music whilst it is pressed and pause the music when it is released.
So instead of using the functionCallPlayerPause function which toggles between play and pause I would like to use functionCallPlayerPlay whilst the button is pressed and functionCallPlayerPauseForce when the button is released.
Any tips on how I might do this?
I tried editing simple_button.py so that it triggers pause when the GPIO exits its looping state but it didn't work too well...
def holdAndRepeatHandler(self, *args):
logger.info('{}: holdAndRepeatHandler'.format(self.name))
# Rise volume as requested
self.when_pressed(*args)
# Detect holding of button
while checkGpioStaysInState(self.hold_time, self.pin, GPIO.LOW):
self.when_pressed(*args)
**self.when_pressed(functionCallPlayerPauseForce)**
[Play]
enabled: True
Type: Button
Pin: 27
pull_up: True
hold_repeat = True
hold_time: 0.3
functionCall: functionCallPlayerPlay
Alternatively, I also tried duplicating the same button in gpio_settings.ini and added a different function depending on the edge parameter but it doesn't always work (don't know if it's actually doing what I want). I'm not sure if I'm confusing the software by duplicating the button. Whenever I do any changes I reset the gpio service to make sure they are applied.
[Play]
enabled: True
Type: Button
Pin: 27
pull_up: True
edge: falling
hold_repeat = False
hold_time: 0.3
functionCall: functionCallPlayerPlay
[Pause]
enabled: True
Type: Button
Pin: 27
edge: rising
hold_repeat = False
pull_up: True
hold_time: 0.3
functionCall: functionCallPlayerPauseForce
Lastly, when keeping the play button held down the music seems to be a bit choppy, I don't know if this is because of the hold_time causing small delays because the button is pressed down? I have set hold_repeat to false though and this issue happens.
Any help would be greatly appreciated thanks :)
I tried creating a new GPIO Device called Long Button which is a modification of Simple Button but takes two actions and uses edge=BOTH but seems that the GPIO service doesn't work... There must be an error somewhere or I'm doing something wrong. Here are the changes I made:
Config file:
[Play]
enabled: True
Type:LongButton
Pin: 27
pull_up: True
hold_repeat: False
hold_time: 0.3
functionCallp: functionCallPlayerPlay
functionCallr: functionCallPlayerPauseForce
New file long_button.py, shown below are the changes vs simple_button.py. I basically tried to modify the callbackFunctionHandler so that it plays action 1 when the button is pressed and action 2 when the button is released but I don't know if I'm doing this right.
class LongButton:
def __init__(self, pin, action=lambda *args: None,action2=lambda *args: None, name=None, bouncetime=500, edge=GPIO.BOTH,
hold_time=.1, hold_repeat=False, pull_up_down=GPIO.PUD_UP):
self.edge = parse_edge_key(edge)
self.hold_time = hold_time
self.hold_repeat = hold_repeat
self.pull_up = True
self.pull_up_down = parse_pull_up_down(pull_up_down)
self.pin = pin
self.name = name
self.bouncetime = bouncetime
GPIO.setup(self.pin, GPIO.IN, pull_up_down=self.pull_up_down)
self._action = action
self._action2 = action2
GPIO.add_event_detect(self.pin, edge=self.edge, callback=self.callbackFunctionHandler,
bouncetime=self.bouncetime)
def callbackFunctionHandler(self, *args):
if (len(args) > 0 and args[0] == self.pin):
logger.debug('args before: {}'.format(args))
args = args[1:]
logger.debug('args after: {}'.format(args))
if GPIO.input(self.pin) == 0:
return self.when_pressed(*args)
if GPIO.input(self.pin) == 1:
return self.when_released(*args)
#if self.hold_repeat:
# return self.holdAndRepeatHandler(*args)
#logger.info('{}: executre callback'.format(self.name))
#return self.when_pressed(*args)
@property
def when_pressed(self):
logger.info('{}: action'.format(self.name))
return self._action
@when_pressed.setter
def when_pressed(self, func):
logger.info('{}: set when_pressed')
self._action = func
GPIO.remove_event_detect(self.pin)
self._action = func
logger.info('add new action')
GPIO.add_event_detect(self.pin, edge=self.edge, callback=self.callbackFunctionHandler, bouncetime=self.bouncetime)
@property
def when_released(self):
return self._action2
@when_released.setter
def when_released(self, func):
self._action2 = func
GPIO.remove_event_detect(self.pin)
self._action2 = func
GPIO.add_event_detect(self.pin, edge=self.edge, callback=self.callbackFunctionHandler, bouncetime=self.bouncetime)
As well as adding this to gpio_control.py
elif device_type == 'LongButton':
return LongButton(config.getint('Pin'),
action=getFunctionCall(config.get('functionCallp')),
action2=getFunctionCall(config.get('functionCallr')),
name=deviceName,
bouncetime=config.getint('bouncetime', fallback=500),
edge=config.get('edge', fallback='BOTH'),
hold_repeat=config.getboolean('hold_repeat', False),
hold_time=config.getfloat('hold_time', fallback=0.3),
pull_up_down=config.get('pull_up_down', fallback=GPIO.PUD_UP))
and editing the init file in GPIODevices to include my long_button.py file:
from .rotary_encoder import RotaryEncoder
from .two_button_control import TwoButtonControl
from .shutdown_button import ShutdownButton
from .simple_button import SimpleButton
from .two_button_control import TwoButtonControl
from .VolumeControl import VolumeControl
from .long_button import LongButton
from .led import *
Any ideas what I might be doing wrong/what I should change?
I managed to get the terminal to output the errors and it seems that most of the issues had to do with tabs vs spaces when writing the files π€¦ββοΈ
It actually seems to work now!! The only thing is when releasing the button I sometimes get this warning in the terminal:
/bin/sleep: missing operand
Try '/bin/sleep --help' for more information.
Sports - Panama
[paused] #6/117 0:11/3:18 (5%)
Is it anything to worry about?
I will clean up the files and link them here in case anyone else is interested.
PR #1406 (not merged yet!) adds many functions to GPIO control, maybe itβs also useful for your use case.