#!/usr/bin/env python3 import _thread import atexit import RPi.GPIO as GPIO import os from waveloader import WaveLoader from rgb import RGBMatrix from rgb import RGB from subprocess import call from time import time from random import randint class Pumpkin: def __init__(self, soundpath, GPIOS_RED = [11], GPIOS_GREEN = [12], GPIOS_BLUE = [13], GPIO_TRIGGER = 15, PWM_FREQUENCY = 60): self.soundfiles = [] self.loadWaveFolder(soundpath) if len(self.soundfiles) == 0: raise IOError('No audio files found in ' + soundpath + '!') GPIO.setmode(GPIO.BOARD) self.GPIOS_RED = GPIOS_RED self.GPIOS_GREEN = GPIOS_GREEN self.GPIOS_BLUE = GPIOS_BLUE self.GPIO_TRIGGER = GPIO_TRIGGER self.GPIO_EVAPORATOR = 0 self.GPIO_PUMP = 0 self.GPIO_POWEROFF = 0 self.fogRuntimeMax = 3 GPIO.setup(self.GPIO_TRIGGER, GPIO.IN) self.rgbControl = RGBMatrix(PWM_FREQUENCY) for r in self.GPIOS_RED: self.rgbControl.addRed(r) for g in self.GPIOS_GREEN: self.rgbControl.addGreen(g) for b in self.GPIOS_BLUE: self.rgbControl.addBlue(b) self.color = RGB(255, 255, 255) self.colorBackground = RGB(0, 0, 0) self.colorFire = RGB(255, 55, 0) atexit.register(self.cleanup) def __del__(self): self.cleanup() def cleanup(self): GPIO.cleanup() def enableFog(self, GPIO_EVAPORATOR, GPIO_PUMP, runtimeSecondsMax = 3): self.GPIO_EVAPORATOR = GPIO_EVAPORATOR self.GPIO_PUMP = GPIO_PUMP self.fogRuntimeMax = runtimeSecondsMax if self.GPIO_EVAPORATOR != 0: GPIO.setup(self.GPIO_EVAPORATOR, GPIO.OUT) if self.GPIO_PUMP != 0: GPIO.setup(self.GPIO_PUMP, GPIO.OUT) self.stopFog() def enablePowerOff(self, GPIO_POWEROFF): self.GPIO_POWEROFF = GPIO_POWEROFF if self.GPIO_POWEROFF != 0: self.powerSwitch = GPIO.setup(self.GPIO_POWEROFF, GPIO.IN) def loadWaveFolder(self, path): if not path.endswith('/'): path += '/' files = os.listdir(path) for f in files: if f.endswith('.wav'): self.soundfiles.append(path + f) def lurk(self): if self.isTurnedOff(): self.poweroff() self.rgbControl.candle(self.colorFire.r, self.colorFire.g, self.colorFire.b, 0.5) def speak(self): self.startFog() soundfile = self.soundfiles[randint(0, len(self.soundfiles) - 1)] sound = WaveLoader(soundfile) duration = sound.frameCount / sound.frameRate t_now = 0 player = _thread.start_new_thread(call, (['aplay', soundfile],)) t_start = time() while t_now < duration: t_now = time() - t_start amplitude = sound.getCurrentLevelRealtime(t_now) if amplitude < 0.1: red = self.colorBackground.r green = self.colorBackground.g blue = self.colorBackground.b else: amplitude = 1 red = self.color.r * amplitude green = self.color.g * amplitude blue = self.color.b * amplitude self.rgbControl.setColor(red, green, blue) if t_now > self.fogRuntimeMax: self.stopFog() self.stopFog() def startFog(self): if self.GPIO_EVAPORATOR != 0: GPIO.output(self.GPIO_EVAPORATOR, True) if self.GPIO_PUMP != 0: GPIO.output(self.GPIO_PUMP, True) def stopFog(self): if self.GPIO_EVAPORATOR != 0: GPIO.output(self.GPIO_EVAPORATOR, False) if self.GPIO_PUMP != 0: GPIO.output(self.GPIO_PUMP, False) def isTriggered(self): return bool(GPIO.input(self.GPIO_TRIGGER)) def isTurnedOff(self): if self.GPIO_POWEROFF == 0: return False return bool(GPIO.input(self.GPIO_POWEROFF)) def poweroff(self): call(['poweroff']) def setAudioColor(self, red, green, blue): self.color = RGB(red, green, blue) def setBackgroundColor(self, red, green, blue): self.colorBackground = RGB(red, green, blue) def setFireColor(self, red, green, blue): self.colorFire = RGB(red, green, blue) def loadAudioFolder(self, path): if os.path.isdir(path): if not path.endswith('/'): path += '/' for file in os.listdir(path): if file.endswith('.wav'): audioFiles.append(audioPath + file) @staticmethod def findAudioFiles(): audioFiles = [] for home in os.listdir('/home'): audioPath = '/home/' + home + '/.config/pumpkin/audio/' if os.path.isdir(audioPath): for file in os.listdir(audioPath): audioFiles.append(audioPath + file) return audioFiles