From 208d12662c220e9d7586486942d2040c0fb4e46e Mon Sep 17 00:00:00 2001 From: Tilman Date: Fri, 30 Nov 2018 08:19:15 +0000 Subject: [PATCH] piplayer4.py --- code/piplayer4.py | 166 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/code/piplayer4.py b/code/piplayer4.py index e69de29..ca310b9 100644 --- a/code/piplayer4.py +++ b/code/piplayer4.py @@ -0,0 +1,166 @@ +# piplayer3 - AudioLauncher +# http://www.tilman.de/piplayer3 + +import RPi.GPIO as GPIO +import logging +import time +import subprocess +import select # for polling zbarcam, see http://stackoverflow.com/a/10759061/3761783 +import os +import urllib +from socketIO_client import SocketIO, LoggingNamespace # https://gist.github.com/ivesdebruycker/4b08bdd5415609ce95e597c1d28e9b9e + + +logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s - %(message)s') +logging.info('Initializing') + +# Configuration +MUSIC_BASE_DIRECTORY = "mnt/NAS/" +SOUND_SCANNING = "~/sounds/scanning.mp3" +SOUND_OK = "~/sounds/ok.mp3" +SOUND_SCAN_FAIL = "~/sounds/fail.mp3" +SOUND_PLAYBACK_ERROR = "~/sounds/error.mp3" +QR_SCANNER_TIMEOUT = 3 + + +pending_play = False +is_paused = True + +# photo sensor on PIN 17 +PIN_SENSOR = 17 + +# IR LED on PIN 22 +PIN_IR_LED = 22 + +# LED on PIN 27 +PIN_LED = 27 + +# Buttons on PINs 9, 10 and 11 +PIN_PREV = 9 +PIN_PLAY = 10 +PIN_NEXT = 11 + +socketIO = SocketIO('127.0.0.1', 3000) + + +GPIO.setmode(GPIO.BCM) +GPIO.setup(PIN_SENSOR, GPIO.IN) +GPIO.setup(PIN_IR_LED, GPIO.OUT) +GPIO.output(PIN_IR_LED, GPIO.LOW) +GPIO.setup(PIN_LED, GPIO.OUT) +GPIO.output(PIN_LED, GPIO.LOW) +GPIO.setup(PIN_PREV, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(PIN_PLAY, GPIO.IN, pull_up_down=GPIO.PUD_UP) +GPIO.setup(PIN_NEXT, GPIO.IN, pull_up_down=GPIO.PUD_UP) + + + +def play_sound(filename): + socketIO.emit('clearQueue') + logging.debug('Cleared queue, now playing ' + filename) + pending_play = True + socketIO.emit('addToQueue', {'uri':filename}) + +def prev_callback(channel): + logging.info("PREVIOUS") + socketIO.emit('previous') + ## TODO implement seek + +def play_callback(channel): + if (is_paused): + logging.info("PLAY") + socketIO.emit('play') + is_paused = False + else: + logging.info("PAUSE") + socketIO.emit('pause') + is_paused = True + +def next_callback(channel): + logging.info("NEXT") + socketIO.emit('next') + ## TODO implement seek + +def on_pushQueue(*args): + logging.debug("pushQueue: " + args[0]) + if pending_play: + if not args[0]: + play_sound(SOUND_PLAYBACK_ERROR) + else: + socketIO.emit('play') + pending_play = False + + +GPIO.add_event_detect(PIN_PREV, GPIO.FALLING, callback=prev_callback, bouncetime=400) +GPIO.add_event_detect(PIN_PLAY, GPIO.FALLING, callback=play_callback, bouncetime=400) +GPIO.add_event_detect(PIN_NEXT, GPIO.FALLING, callback=next_callback, bouncetime=400) + + +try: + # play_sound(SOUND_OK) + + socketIO.on('pushQueue', on_pushQueue) + + while True: + logging.info('Wait for photo sensor') + GPIO.wait_for_edge(PIN_SENSOR, GPIO.RISING) + + logging.info('Photo sensor active, activating light and camera') + play_sound(SOUND_SCANNING) + + # turn LED on + GPIO.output(PIN_LED, GPIO.HIGH) + + # scan QR code + zbarcam = subprocess.Popen(['zbarcam', '--quiet', '--nodisplay', '--raw', '-Sdisable', '-Sqrcode.enable', '--prescale=320x240', '/dev/video0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + poll_obj = select.poll() + poll_obj.register(zbarcam.stdout, select.POLLIN) + + # wait for scan result (or timeout) + start_time = time.time() + poll_result = False + while ((time.time() - start_time) < QR_SCANNER_TIMEOUT and (not poll_result)): + poll_result = poll_obj.poll(100) + + if (poll_result): + + # play confirmation sound + play_sound(SOUND_OK) + socketIO.emit('removeFromQueue', 0) + + qr_code = zbarcam.stdout.readline().rstrip() + qr_code = qr_code.decode("utf-8") # python3 + logging.info("QR Code: " + qr_code) + + pending_play = True + + if (not (qr_code.startswith("http://")): + # create full path + if (qr_code.startswith("/")): + qr_code = qr_code[1:] + full_path = MUSIC_BASE_DIRECTORY + qr_code + socketIO.emit('addToQueue', {'uri':full_path}) + else: + socketIO.emit('addToQueue', {'service':'webradio','uri':qr_code}) + + else: + logging.warning('Timeout on zbarcam') + play_sound(SOUND_SCAN_FAIL) + + zbarcam.terminate() + GPIO.output(PIN_LED, GPIO.LOW) + + # wait until sensor is not blocked anymore + if (GPIO.input(PIN_SENSOR) == GPIO.HIGH): + GPIO.wait_for_edge(PIN_SENSOR, GPIO.FALLING) + time.sleep(1) + + +# Exit when Ctrl-C is pressed +except KeyboardInterrupt: + logging.info('Shutdown') + +finally: + logging.info('Reset GPIO configuration and close') + GPIO.cleanup()