Source

media_control_buttons / media_control.py

Full commit
#!/usr/bin/env python

import time
import os
import RPi.GPIO as GPIO

import os
import sys

class Press(object):
    def __init__(self,
                 func=None, pin=None,
                 trigger_after=0, trigger_until=None,
                 repeat_after=None):
        self.func = func
        self.pin = pin
        self.trigger_after = trigger_after
        self.trigger_until = trigger_until
        self.repeat_after = repeat_after


def SimplePress(pin, func):
    return Press(func=func, pin=pin)


def ShortPress(pin, func):
    return Press(pin=pin, func=func,
                 trigger_until=0.2)


def LongPress(pin, func, **kwargs):
    return Press(pin=pin, func=func,
                 trigger_after=1.5,
                 **kwargs)


def reset1():
    os.system("/etc/init.d/mpd stop")
    time.sleep(1)
    os.system("/etc/init.d/mpd start")


def reset2():
    os.system("shutdown -r now")


def mpc_command(cmd):
    def f():
        os.system("mpc %s" % cmd)
    return f


ACTIONS = [
    SimplePress(27, mpc_command('toggle')),
    Press(pin=27, func=reset1,
          trigger_after=0.3,
          trigger_until=2.0,
          ),

    Press(pin=27, func=reset2,
          trigger_after=2.1,
          trigger_until=4.0,
          ),


    ShortPress(22, mpc_command('prev')),
    LongPress(22, mpc_command('seek -10'),
              repeat_after=0.8),

    ShortPress(17, mpc_command('next')),
    LongPress(17, mpc_command('seek +10'),
              repeat_after=0.8),
]


def setup():
    GPIO.setmode(GPIO.BCM)
    for action in ACTIONS:
        GPIO.setup(action.pin, GPIO.IN)


def mainloop():
    INTERVAL = 0.02
    pressed = dict()
    while True:
        for action in ACTIONS:
            if GPIO.input(action.pin) == False: # pressed
                if action not in pressed:
                    pressed[action] = 0
                else:
                    pressed[action] += INTERVAL
                if action.trigger_until is None:
                    # Need to wait until it has been pressed for
                    # at least trigger_after, but less than trigger_after + 1 INTERVAL
                    if  0 <= pressed[action] - action.trigger_after < INTERVAL:
                        action.func()
                        if action.repeat_after is not None:
                            # By subtracting 'action.repeat_after',
                            # we know it will be up for repeated after that interval
                            pressed[action] -= action.repeat_after
            else:
                if action in pressed:
                    # For items that have trigger_until defined, we can only
                    # process when they unpress, because we have to verify that
                    # they were unpressed before trigger_until.
                    if action.trigger_until is not None:
                        pressed_for = pressed[action]
                        if action.trigger_after <= pressed_for < action.trigger_until:
                            action.func()
                    del pressed[action]

        time.sleep(INTERVAL)

def main():
    setup()
    mainloop()


if __name__ == '__main__':
    main()