renaming folders and files to python format
This commit is contained in:
		
							parent
							
								
									ade378d128
								
							
						
					
					
						commit
						798775805c
					
				| @ -18,7 +18,6 @@ class ThreadedUDPServer(threading.Thread): | ||||
|         self.start() | ||||
|         self.udpClientGuardian = self.UDPClientGuardian() | ||||
|         self.udpClientGuardian.start() | ||||
|         UDPClients | ||||
| 
 | ||||
| 
 | ||||
|     def run(self): | ||||
| @ -86,13 +85,6 @@ class UDPClient(): | ||||
|         self.lastping = time() | ||||
| 
 | ||||
|     def handle(self, request): | ||||
| 
 | ||||
|         clientdata = request[0].decode() | ||||
|         self.socket = request[1] | ||||
|         #print(time(),"{} wrote:".format(self.client_address)) | ||||
|         #print(time(),"clientdata -> ", clientdata) | ||||
|         # socket.sendto(bytes("pong","utf-8"),self.client_address) | ||||
| 
 | ||||
|         # Client Types: | ||||
|         # CLIENT_TYPE_CONTROLLER = 0 | ||||
|         # CLIENT_TYPE_STRIPE = 1 | ||||
| @ -104,8 +96,9 @@ class UDPClient(): | ||||
|         # s:ping | ||||
|         # UDP  | ||||
| 
 | ||||
|         self.socket = request[1] | ||||
|         try: | ||||
|             data = clientdata.split(':') | ||||
|             data = request[0].decode().split(':') | ||||
|             #print(data) | ||||
|             # r:1:srg strip name | ||||
|             if data[0] == "r" and int(data[1]) == CLIENT_TYPE_STRIPE and data[2] != None and self.registered is False: | ||||
|  | ||||
| @ -22,8 +22,8 @@ class ThreadedWebSocketServer(Thread): | ||||
| 
 | ||||
| import json | ||||
| 
 | ||||
| from rgbUtils import effectControllerJsonHelper | ||||
| from rgbUtils import rgbStripControllerJsonHelper | ||||
| from BackendProvider.Helper import effectControllerJsonHelper | ||||
| from BackendProvider.Helper import rgbStripControllerJsonHelper | ||||
| 
 | ||||
| import traceback | ||||
| import logging | ||||
| @ -63,12 +63,6 @@ class HTTPWebSocketsHandler(WebSocket): | ||||
|                     ledcount=1 | ||||
|                     if "led_count" in data: | ||||
|                         ledcount = int(data["led_count"]) | ||||
|                     self.nojson=0 | ||||
|                     if "nojson" in data: | ||||
|                         self.nojson = int(data["nojson"]) | ||||
|                     self.nosend=0 | ||||
|                     if "nosend" in data: | ||||
|                         self.nosend = int(data["nosend"]) | ||||
|                      | ||||
|                     # registers the strip with websocket object and name. the onRGBStripValueUpdate(rgbStrip) is called by  | ||||
|                     # by the rgbStrip when an effectThread updates it | ||||
| @ -87,13 +81,9 @@ class HTTPWebSocketsHandler(WebSocket): | ||||
|                     }) | ||||
|                 ) | ||||
|                 return | ||||
| 
 | ||||
|             # the stripe should usualy not send any data, i do not know why it should... | ||||
|             elif self.client_type is CLIENT_TYPE_STRIPE: | ||||
|                 if self.nosend == 1: | ||||
|                     respdata = "d" | ||||
|                     for i in range(self.rgbStrip.STRIP_LENGHT): | ||||
|                         respdata += ":" + str(i) + ":"+str(self.rgbStrip.red[i])+":"+str(self.rgbStrip.green[i])+":"+str(self.rgbStrip.blue[i]) | ||||
|                     self.sendMessage(respdata) | ||||
|                 return | ||||
|             # audio recorder responses are handled by the effectControllerJsonHandler | ||||
|             elif self.client_type is CLIENT_TYPE_RECORDER: | ||||
| @ -139,15 +129,8 @@ class HTTPWebSocketsHandler(WebSocket): | ||||
| 
 | ||||
|     # when a rgbStrip value is changed, send json data to client | ||||
|     def onRGBStripValueUpdate(self,rgbStrip): | ||||
|         if self.nosend == 0: | ||||
|             if self.nojson == 0: | ||||
|                 self.sendMessage( | ||||
|                     json.dumps({ | ||||
|                         'data': rgbStripControllerJsonHelper.getRGBData(rgbStrip) | ||||
|                     }) | ||||
|                 ) | ||||
|             if self.nojson == 1: | ||||
|                 respdata = "d" | ||||
|                 for i in range(rgbStrip.STRIP_LENGHT): | ||||
|                     respdata += ":" + str(i) + ":"+str(rgbStrip.red[i])+":"+str(rgbStrip.green[i])+":"+str(rgbStrip.blue[i]) | ||||
|                 self.sendMessage(respdata) | ||||
|         self.sendMessage( | ||||
|             json.dumps({ | ||||
|                 'data': rgbStripControllerJsonHelper.getRGBData(rgbStrip) | ||||
|             }) | ||||
|         ) | ||||
|  | ||||
| @ -1,15 +1,13 @@ | ||||
| from rgbUtils.BaseEffect import BaseEffect | ||||
| from rgbUtils.EffectParameter import slider, colorpicker | ||||
| from rgbUtils.debug import debug | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| from Utils.EffectParameter import slider, colorpicker | ||||
| import time | ||||
| 
 | ||||
| import sys | ||||
| import numpy | ||||
| from rgbUtils.pyAudioRecorder import pyAudioRecorder | ||||
| from time import perf_counter, sleep | ||||
| from random import randint, shuffle | ||||
| 
 | ||||
| class musikEffect(BaseEffect): | ||||
| class MusikEffect(BaseEffect): | ||||
|     name = "musikEffect" | ||||
|     desc = "LED-Band *sollte* nach musik blinken" | ||||
|      | ||||
| @ -18,7 +16,7 @@ class musikEffect(BaseEffect): | ||||
|     # Something that will be used to show descriptions and value options  | ||||
|     # of the parameters the effect will accept, in a way, that eg the webclient can decide,  | ||||
|     # if the parameters can be toggeled by a button/checkbox/slider/whatever | ||||
|     effectParameters = [ | ||||
|     effectParameters: list = [ | ||||
|     #     radio(\    | ||||
|     #         "Shuffle LED to Freq Order",\ | ||||
|     #         "Off -> Mapping  ",\ | ||||
| @ -42,12 +40,14 @@ class musikEffect(BaseEffect): | ||||
|         self.fft_random_keys = [0,1,2,3] | ||||
|         self.fft_random = [0,0,0,0] | ||||
| 
 | ||||
|         self.y_max_freq_avg_list = [] | ||||
|         self.low_freq_avg_list = [] | ||||
|         self.bpm_list = [] | ||||
|         self.prev_beat = 0 # timestamp | ||||
| 
 | ||||
|         # used by strobe()  | ||||
|         self.lastmode = 0 | ||||
| 
 | ||||
|         self.recorderClient = pyAudioRecorder.recorderClient() | ||||
|         self.rgbStripController.pyAudioRecorder.registerRecorderClient(self.recorderClient) | ||||
| 
 | ||||
|         return | ||||
| 
 | ||||
|     #loop effect as long as not stopped | ||||
| @ -67,17 +67,17 @@ class musikEffect(BaseEffect): | ||||
|         #        b=0 | ||||
|         #    RGBStrip.RGB(r,g,b) | ||||
|         #self.lastTime = time.time() | ||||
|         sleep(.001) | ||||
|         sleep(0.00833333333) | ||||
| 
 | ||||
|     def end(self): | ||||
|        self.rgbStripController.pyAudioRecorder.unregisterRecorderClient(self.recorderClient) | ||||
|         pass | ||||
| 
 | ||||
|     def plot_audio_and_detect_beats(self): | ||||
|         if not self.rgbStripController.pyAudioRecorder.has_new_audio:  | ||||
|         if not self.hasNewFttValues:  | ||||
|             return | ||||
| 
 | ||||
|         # get x and y values from FFT | ||||
|         xs, ys = self.rgbStripController.pyAudioRecorder.fft() | ||||
|         xs, ys = self.ftt | ||||
| 
 | ||||
|         # calculate average for all frequency ranges | ||||
|         y_avg = numpy.mean(ys) | ||||
| @ -88,9 +88,9 @@ class musikEffect(BaseEffect): | ||||
|         #mid_freq = numpy.mean(ys[88:115]) | ||||
|         #hig_freq = numpy.mean(ys[156:184]) | ||||
|          | ||||
|         low_freq = numpy.mean(ys[0:67]) | ||||
|         mid_freq = numpy.mean(ys[68:135]) | ||||
|         hig_freq = numpy.mean(ys[136:204]) | ||||
|         low_freq = numpy.mean(ys[0:int(ys.__len__() / 3 * 1)]) | ||||
|         mid_freq = numpy.mean(ys[int(ys.__len__() / 3 * 1):int(ys.__len__() / 3 * 2)]) | ||||
|         hig_freq = numpy.mean(ys[int(ys.__len__() / 3 * 2):int(ys.__len__() / 3 * 3)]) | ||||
|          | ||||
|         #get the maximum of all freq | ||||
|         if len(self.y_max_freq_avg_list) < 250 or y_avg > 10 and numpy.amax([low_freq,mid_freq,hig_freq])/2 > numpy.amin(self.y_max_freq_avg_list): | ||||
| @ -166,6 +166,16 @@ class musikEffect(BaseEffect): | ||||
|                     self.fft_random[1], | ||||
|                     self.fft_random[2] | ||||
|                 ) | ||||
|             """ | ||||
|             rgbStrip: RGBStrip | ||||
|             for rgbStrip in self.effectRGBStrips(): | ||||
|                 for i in range(rgbStrip.STRIP_LENGHT): | ||||
|                     if rgbStrip.STRIP_LENGHT-1-10 is not i: | ||||
|                         rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, rgbStrip.red[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.green[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.blue[rgbStrip.STRIP_LENGHT-i-2]) | ||||
|                     else: | ||||
|                         rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, self.fft_random[0], self.fft_random[1], self.fft_random[2]) | ||||
|                 rgbStrip.show() | ||||
|             """ | ||||
|          | ||||
|         # shorten the cumulative list to account for changes in dynamics | ||||
|         if len(self.low_freq_avg_list) > 500: | ||||
| @ -187,8 +197,7 @@ class musikEffect(BaseEffect): | ||||
|             self.low_freq_avg_list = [] | ||||
|             print("new song") | ||||
|             self.off() | ||||
| 
 | ||||
|         self.rgbStripController.pyAudioRecorder.newAudio = False | ||||
|         self.hasNewFttValues = False | ||||
|         # print(self.bpm_list)250 | ||||
| 
 | ||||
|     def strobe(self): | ||||
							
								
								
									
										184
									
								
								server/Effects/MusikEffect2.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								server/Effects/MusikEffect2.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,184 @@ | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| from Utils.RGBStrip import RGBStrip | ||||
| from Utils.EffectParameter import slider, colorpicker | ||||
| import time | ||||
| 
 | ||||
| import sys | ||||
| import numpy | ||||
| from time import perf_counter, sleep | ||||
| from random import randint, shuffle | ||||
| 
 | ||||
| import typing | ||||
| 
 | ||||
| import matplotlib | ||||
| import matplotlib.pyplot as plt | ||||
| #matplotlib.use('TkAgg') # THIS MAKES IT FAST! | ||||
| matplotlib.get_backend() | ||||
| 
 | ||||
| class MusikEffect2(BaseEffect): | ||||
|     name = "musikEffect2" | ||||
|     desc = "LED-Band *sollte* nach musik blinken" | ||||
|      | ||||
|      | ||||
|      | ||||
|     # Something that will be used to show descriptions and value options  | ||||
|     # of the parameters the effect will accept, in a way, that eg the webclient can decide,  | ||||
|     # if the parameters can be toggeled by a button/checkbox/slider/whatever | ||||
|     """radio(  | ||||
|         "Shuffle LED to Freq Order", | ||||
|         "Off -> Mapping  ", | ||||
|         [ | ||||
|             [0,255,255,"red"], | ||||
|             [0,255,255,"green"], | ||||
|             [0,255,255,"blue"] | ||||
|         ] | ||||
|     ),""" | ||||
|     effectParameters: list = [ | ||||
|         slider( | ||||
|             "Effect Brightnes", | ||||
|             "Choose a brightness for your LED's", | ||||
|             [ | ||||
|                  [0,100,100,"brightness"], | ||||
|              ] | ||||
|          ) | ||||
|     ] | ||||
| 
 | ||||
|     def init(self): | ||||
|          | ||||
|          | ||||
|         self.fft_random_keys = [0,1,2,3] | ||||
|         self.fft_random = [0,0,0,0] | ||||
| 
 | ||||
|         self.y_max_freq_avg_list = [0] | ||||
|         self.low_freq_avg_list = [0] | ||||
|         self.bpm_list = [] | ||||
|         self.prev_beat = 0 # timestamp | ||||
| 
 | ||||
|         ''' | ||||
|         self.fig = plt.gcf() | ||||
|          | ||||
|         self.fig.show() | ||||
|         ''' | ||||
|         return | ||||
| 
 | ||||
| 
 | ||||
|     #loop effect as long as not stopped | ||||
|     def effect(self): | ||||
|         '''plt.clf() | ||||
|         #plt.ylim(-.5, numpy.amax(self.y_max_freq_avg_list)) | ||||
|         plt.xlabel('xs') | ||||
|         plt.ylabel('ys') | ||||
|         plt.plot(self.ftt[0],self.ftt[1]) | ||||
|         self.fig.canvas.draw() | ||||
|         self.fig.canvas.flush_events()''' | ||||
|         self.plot_audio_and_detect_beats() | ||||
|         #self.freqtocolor() | ||||
|         #if(time.time() - self.lastTime >= 0.002): | ||||
|         #for RGBStrip in self.effectRGBStrips(): | ||||
|         #    r= RGBStrip.red-1 | ||||
|         #    if(r<0): | ||||
|         #        r=0 | ||||
|         #    g= RGBStrip.green-1 | ||||
|         #    if(g<0): | ||||
|         #        g=0 | ||||
|         #    b= RGBStrip.blue-1  | ||||
|         #    if(b<0): | ||||
|         #        b=0 | ||||
|         #    RGBStrip.RGB(r,g,b) | ||||
|         #self.lastTime = time.time() | ||||
|         sleep(0.00833333333) | ||||
| 
 | ||||
|     def end(self): | ||||
|         pass | ||||
| 
 | ||||
|     def plot_audio_and_detect_beats(self): | ||||
|         if not self.hasNewFttValues:  | ||||
|             return | ||||
| 
 | ||||
|         # get x and y values from FFT | ||||
|         xs, ys = self.ftt | ||||
| 
 | ||||
|         amax = numpy.amax(ys) | ||||
|         if amax > 0: | ||||
|             self.y_max_freq_avg_list.append(amax) | ||||
|         if len(self.y_max_freq_avg_list ) > 50000: | ||||
|             self.y_max_freq_avg_list = self.y_max_freq_avg_list[25000:] | ||||
| 
 | ||||
|         calc = numpy.amax(ys) / numpy.amax(self.y_max_freq_avg_list) * 765 | ||||
|         """print(amax) | ||||
|         print(numpy.amax(self.y_max_freq_avg_list)) | ||||
|         print(calc) | ||||
|         print("-----------") | ||||
|         """ | ||||
|         c: self.Color = self.pitchRainbow(calc) | ||||
|         rgbStrip: RGBStrip | ||||
|         for rgbStrip in self.effectRGBStrips(): | ||||
|             """ | ||||
|             for i in range(rgbStrip.STRIP_LENGHT): | ||||
|                 if rgbStrip.STRIP_LENGHT-1-10 is not i: | ||||
|                     rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, rgbStrip.red[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.green[rgbStrip.STRIP_LENGHT-i-2], rgbStrip.blue[rgbStrip.STRIP_LENGHT-i-2]) | ||||
|                 else: | ||||
|                     rgbStrip.WS2812b(rgbStrip.STRIP_LENGHT-i-1, c.red, c.green, c.blue) | ||||
|             rgbStrip.show() | ||||
|             """ | ||||
|             rgbStrip.RGB(int(c.red),int(c.green),int(c.blue)) | ||||
|         # shorten the cumulative list to account for changes in dynamics | ||||
|          | ||||
|              | ||||
|     def pitchRainbow(self,p: float): | ||||
|         if p < 1: | ||||
|             return self.Color(0,0,0) | ||||
|         elif p < 255: | ||||
|             return self.Color(255 - p % 255,p % 255,0) | ||||
|         elif p < 510: | ||||
|             return self.Color(0,255 - p % 255,p % 255) | ||||
|         else: | ||||
|             return self.Color(p % 255,0,255 - p % 255) | ||||
| 
 | ||||
|     def pitchConv(self,p: float): | ||||
| 
 | ||||
|         r:float | ||||
|         g:float | ||||
|         b:float | ||||
| 
 | ||||
|         if p < 40: | ||||
|             return self.Color(255,0,0) | ||||
|          | ||||
|         elif p >= 40 and p <= 77 :  | ||||
|             b = (p - 40) * (255/37.0000) | ||||
|             return self.Color(255,0,b) | ||||
|          | ||||
|         elif p > 77 and p <= 205: | ||||
|             r = 255 - ((p - 78) * 2) | ||||
|             return self.Color(r,0,255) | ||||
|          | ||||
|         elif p >= 206 and p <= 238: | ||||
|             g = (p - 206) * (255/32.0000) | ||||
|             return self.Color(0,g,255) | ||||
|          | ||||
|         elif p <= 239 and p <= 250: | ||||
|             r = (p - 239) * (255/11.0000) | ||||
|             return self.Color(r, 255, 255) | ||||
|          | ||||
|         elif p >= 251 and p <= 270: | ||||
|             return self.Color(255, 255, 255) | ||||
|          | ||||
|         elif p >= 271 and p <= 398: | ||||
|             rb = 255-((p-271)*2) | ||||
|             return self.Color(rb, 255, rb) | ||||
|          | ||||
|         elif p >= 398 and p <= 650: | ||||
|             return self.Color(0, 255-(p-398), (p-398)) | ||||
|          | ||||
|         else: | ||||
|             return self.Color(255, 0, 0) | ||||
|          | ||||
| 
 | ||||
|     class Color: | ||||
|         red: float  | ||||
|         green: float | ||||
|         blue: float | ||||
|         def __init__(self,red:float,green:float,blue:float) -> None: | ||||
|             self.red = red | ||||
|             self.green = green | ||||
|             self.blue = blue | ||||
| @ -1,9 +1,8 @@ | ||||
| from rgbUtils.BaseEffect import BaseEffect | ||||
| from rgbUtils.debug import debug | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| 
 | ||||
| import time | ||||
| 
 | ||||
| class offEffect(BaseEffect): | ||||
| class OffEffect(BaseEffect): | ||||
|     name = "offEffect" | ||||
|     desc = "LED-Band *sollte* nicht an sein" | ||||
| 
 | ||||
| @ -1,9 +1,8 @@ | ||||
| from rgbUtils.BaseEffect import BaseEffect | ||||
| from rgbUtils.EffectParameter import slider, colorpicker | ||||
| from rgbUtils.debug import debug | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| from Utils.EffectParameter import slider, colorpicker | ||||
| import time | ||||
| 
 | ||||
| class onEffect(BaseEffect): | ||||
| class OnEffect(BaseEffect): | ||||
|     name = "onEffect" | ||||
|     desc = "LED-Band *sollte* an sein" | ||||
|      | ||||
| @ -1,8 +1,7 @@ | ||||
| from rgbUtils.BaseEffect import BaseEffect | ||||
| from rgbUtils.debug import debug | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| import time | ||||
| 
 | ||||
| class rainbowEffect(BaseEffect): | ||||
| class RainbowEffect(BaseEffect): | ||||
|     name = "rainbowEffect" | ||||
|     desc = "LED-Band *sollte* rainbowEffect sein" | ||||
| 
 | ||||
| @ -13,7 +12,6 @@ class rainbowEffect(BaseEffect): | ||||
| 
 | ||||
|     #loop effect as long as not stopped | ||||
|     def effect(self): | ||||
|         debug(self) | ||||
|         """Draw rainbow that fades across all pixels at once.""" | ||||
|         for j in range(256*75): | ||||
|             for rgbStrip in self.effectRGBStrips(): | ||||
| @ -1,9 +1,8 @@ | ||||
| from rgbUtils.BaseEffect import BaseEffect | ||||
| from rgbUtils.debug import debug | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| from random import randint | ||||
| import time | ||||
| 
 | ||||
| class strobeEffect(BaseEffect): | ||||
| class StrobeEffect(BaseEffect): | ||||
|     name = "strobeEffect" | ||||
|     desc = "*Strobe*" | ||||
| 
 | ||||
| @ -1,21 +1,26 @@ | ||||
| import time | ||||
| import threading | ||||
| import typing | ||||
| import copy | ||||
| from rgbUtils.debug import debug | ||||
| 
 | ||||
| class BaseEffect(threading.Thread): | ||||
| 
 | ||||
|     # The Name and the Description of the Effect,  | ||||
|     # should be overwritten by the inheritancing Effect | ||||
|     name = "Undefined" | ||||
|     desc = "No Description" | ||||
|     name: str = "Undefined" | ||||
|     desc: str = "No Description" | ||||
| 
 | ||||
|     # Something that will be used to show descriptions and value options  | ||||
|     # of the parameters the effect will accept, in a way, that eg the webclient can decide,  | ||||
|     # if the parameters can be toggeled by a button/checkbox/slider/whatever | ||||
|     effectParameters = [] | ||||
|     effectParameters: list = [] | ||||
| 
 | ||||
|     stop = False | ||||
|     # musiceffect things  | ||||
|     # TODO we need a recorderController where the effect binds to and gets its values, this is shit... | ||||
|     hasNewFttValues = False | ||||
|     ftt: typing.Tuple[typing.List[float],typing.List[float]] = ([],[]) | ||||
| 
 | ||||
|     stop:bool = False | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         threading.Thread.__init__(self) | ||||
| @ -48,7 +53,7 @@ class BaseEffect(threading.Thread): | ||||
|     # to avoid two effects accessing the rgbStrip | ||||
|     def effect(self): | ||||
|         while 1: | ||||
|             debug("ET "+self.name+" effect() function needs to be replaced in inheritancing Effect") | ||||
|             print("ET "+self.name+" effect() function needs to be replaced in inheritancing Effect") | ||||
| 
 | ||||
|     # called when the effect is stopped | ||||
|     def end(self): | ||||
| @ -75,6 +80,10 @@ class BaseEffect(threading.Thread): | ||||
|     def onEffectParameterValuesUpdated(self): | ||||
|         return | ||||
| 
 | ||||
|     def updateFttValues(self,ftt: typing.Tuple[typing.List[float],typing.List[float]]): | ||||
|         self.hasNewFttValues = True | ||||
|         self.ftt = ftt | ||||
| 
 | ||||
|     # returns a list of the RGBStrips used by this effect | ||||
|     def effectRGBStrips(self): | ||||
|         return self.effectRGBStripList | ||||
							
								
								
									
										245
									
								
								server/Utils/EffectController.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								server/Utils/EffectController.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,245 @@ | ||||
| # import offEffect | ||||
| 
 | ||||
| from Effects.OffEffect import OffEffect | ||||
| from Utils.BaseEffect import BaseEffect | ||||
| 
 | ||||
| import time | ||||
| import threading | ||||
| import os | ||||
| import sys | ||||
| 
 | ||||
| #TypeCheck | ||||
| from typing import Type, List | ||||
| from Utils.RGBStrip import RGBStrip | ||||
| from Utils.RGBStripController import RGBStripController | ||||
| 
 | ||||
| 
 | ||||
| class EffectController: | ||||
|     ''' | ||||
|     the effectController handles the effects and pushes the values to the rgbStripContoller | ||||
|     it also calls the backendProvider's onChange function when there are changes made on the effects: | ||||
|      | ||||
|      - start/stop effects | ||||
|      - changes parameters of specific effects | ||||
|      - moves the rgbStrips to the effects | ||||
|      - runs a guardian that detects dead effectThreads and moves Strips to offEffect | ||||
|     ''' | ||||
|      | ||||
|     rememberRGBStripEffectThreads: dict = {} | ||||
| 
 | ||||
|     # list of current running effects | ||||
|     effectThreads: List[BaseEffect] = [] | ||||
|     # the always running base effect | ||||
|     offEffectThreadObject: BaseEffect | ||||
|     # maybe i will seperate this later | ||||
|     onControllerChangeHandler: List[Type[object]] = [] | ||||
|     #rgbStripController | ||||
|     rgbStripController: RGBStripController | ||||
|   | ||||
|     def __init__(self,rgbStripController: RGBStripController) -> None: | ||||
|         '''Init the EffectController with the RGBStripController''' | ||||
|         self.rgbStripController = rgbStripController | ||||
|         # load the effects | ||||
|         self.effectsList: List[Type[BaseEffect]] = self.getEffectsListFromDir() | ||||
|         # start the offEffect by default | ||||
|         self.offEffectThreadObject = self.startEffect(OffEffect,[]) | ||||
|          | ||||
|         # - a bit of failover handling, remove dead threads from effectThread array | ||||
|         # - move strips without an effect to the offEffect | ||||
|         self.effectGuardian = self.EffectGuardian(self) | ||||
|         self.effectGuardian.start() | ||||
| 
 | ||||
|      | ||||
|     def startEffect(self, effectClass: Type[BaseEffect], rgbStrips: list, params: list = []) -> BaseEffect: #TODO params as a object -> EffectParams | ||||
|         '''starts a effect by given class, rgbStrips and params ([[index,[param,param,param]],[index,[param,param,param]]])''' | ||||
|         newEffect = effectClass() | ||||
|         if len(self.effectThreads) > 0 and len(rgbStrips) > 0 or len(self.effectThreads) == 0: | ||||
|             newEffect.start() | ||||
|             self.updateEffectParameters(newEffect, params) | ||||
|             self.effectThreads.append(newEffect) | ||||
| 
 | ||||
|             for rgbStrip in rgbStrips: | ||||
|                 self.moveRGBStripToEffectThread(rgbStrip, newEffect) | ||||
|              | ||||
|         self.noticeControllerChange() | ||||
|         return newEffect | ||||
| 
 | ||||
|      | ||||
|     def getEffects(self) -> List[Type[BaseEffect]]: | ||||
|         ''' | ||||
|         returns all effectClasses but offEffect, since offEffect will never be killed | ||||
|         and should not be running twice | ||||
|         ''' | ||||
|         # alle außer offEffect | ||||
|         return self.effectsList | ||||
| 
 | ||||
|      | ||||
|     def getEffectThreads(self) -> List[BaseEffect]: | ||||
|         '''returns all running effectThreads''' | ||||
|         return self.effectThreads | ||||
|          | ||||
|      | ||||
|     def getEffectRGBStrips(self, effectThreadObject: BaseEffect) -> List[RGBStrip]: | ||||
|         '''returns a list of the RGBStrips used by this effect''' | ||||
|         return effectThreadObject.effectRGBStrips() | ||||
| 
 | ||||
|      | ||||
|     def moveRGBStripToEffectThread(self, rgbStrip: RGBStrip, effectThreadObject: BaseEffect) -> None: | ||||
|         '''move a rgbStip to a running effectThread''' | ||||
|         # cycle throught all effects and  | ||||
|         # remove Strip from effect if added | ||||
|         for et in self.effectThreads: | ||||
|             if rgbStrip in et.effectRGBStrips(): | ||||
|                 et.removeRGBStrip(rgbStrip) | ||||
|         if effectThreadObject.isAlive(): | ||||
|             self.rememberRGBStripEffectThreads[rgbStrip.STRIP_NAME] = et | ||||
|             effectThreadObject.addRGBStrip(rgbStrip) | ||||
|              | ||||
|         # check if any effectThread has no more rgbStrips and if so, stop it | ||||
|         # if the effectThread has no more strips, we stop it and remove it. | ||||
|         for x, effectThread in enumerate(self.effectThreads): | ||||
|             # but ignore the first effectthread, since that is our offeffect that should never be killed | ||||
|             if len(effectThread.effectRGBStrips()) == 0 and x is not 0: | ||||
|                 effectThread.stopEffect() | ||||
|                 self.effectThreads.remove(effectThread) | ||||
|         self.noticeControllerChange() | ||||
|          | ||||
|      | ||||
|     def updateEffectParameters(self, effectThreadObject: BaseEffect, effectParameters: list): | ||||
|         '''updates parameter of a running effectThread ([[index,[param,param,param]],[index,[param,param,param]]])''' | ||||
|         for effectParameter in effectParameters: | ||||
|             effectThreadObject.updateEffectParameterValues( | ||||
|                 effectParameter[0], effectParameter[1]) | ||||
|         self.noticeControllerChange() | ||||
| 
 | ||||
|      | ||||
|     def stopAll(self): | ||||
|         '''stops all effectThreads and set the rgbStrips to off''' | ||||
|         print("effectController stopAll()") | ||||
|         for effectThread in self.effectThreads: | ||||
|             print("effectController killing... "+str(effectThread)) | ||||
|             effectThread.stopEffect() | ||||
|             print("effectController killed "+str(effectThread)) | ||||
| 
 | ||||
|         print("effectController stopping Guardian... ") | ||||
|         self.effectGuardian.stop() | ||||
|         print("effectController stopped Guardian") | ||||
| 
 | ||||
|         time.sleep(0.5) | ||||
| 
 | ||||
|      | ||||
|     def noticeControllerChange(self) -> None: | ||||
|         '''inform the controllerChangeHandler to update the client''' | ||||
|         for controllerChangeHandler in self.onControllerChangeHandler: | ||||
|             controllerChangeHandler() | ||||
| 
 | ||||
|     def addOnControllerChangeHandler(self, hander: Type[object]) -> None: #TODO class instead of function for OnControllerChangeHandler? | ||||
|         '''add onControllerChangeHandler''' | ||||
|         print("addOnControllerChangeHandler", str(hander)) | ||||
|         self.onControllerChangeHandler.append(hander) | ||||
|         # send data to this client | ||||
|         hander() | ||||
| 
 | ||||
|      | ||||
|     def removeOnControllerChangeHandler(self, hander: Type[object]): #TODO class instead of function for OnControllerChangeHandler? | ||||
|         '''remove onControllerChangeHandler''' | ||||
|         print("removeOnControllerChangeHandler", str(hander)) | ||||
|         if hander in self.onControllerChangeHandler: | ||||
|             self.onControllerChangeHandler.remove(hander) | ||||
|         else: | ||||
|             print('\n\n -> client was never registered!') | ||||
| 
 | ||||
|       | ||||
|     def getEffectsListFromDir(self) -> List[Type[BaseEffect]]: | ||||
|         '''automaticly loads all modules from effects subdir and adds them to the list of effects if they have the BaseEffect as subclass''' | ||||
|         effectsList: List[Type[BaseEffect]] = [] | ||||
|         for raw_module in os.listdir(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__), os.pardir),"Effects"))): | ||||
|              | ||||
|             if raw_module == '__init__.py' or raw_module == 'OffEffect.py' or raw_module[-3:] != '.py': | ||||
|                 continue | ||||
|             effectModule = __import__("Effects."+raw_module[:-3], fromlist=[raw_module[:-3]]) | ||||
|             effectClass = getattr(effectModule, raw_module[:-3]) | ||||
|             if issubclass(effectClass,BaseEffect): | ||||
|                 effectsList.append(effectClass) | ||||
|         print("Loaded effects: ",effectsList) | ||||
|         return effectsList | ||||
| 
 | ||||
|      | ||||
|     def onRGBStripRegistered(self,rgbStrip: RGBStrip): | ||||
|         ''' moves new rgbStrip to the offEffectThread and notice all Controller Clients''' | ||||
|         if rgbStrip.STRIP_NAME in self.rememberRGBStripEffectThreads: | ||||
|             restoredEffect: BaseEffect = self.rememberRGBStripEffectThreads[rgbStrip.STRIP_NAME] | ||||
|             if restoredEffect.isAlive(): | ||||
|                 print("stripname in rememberRGBStripEffectThreads -> same effect was never stopped, move to") | ||||
|                 self.moveRGBStripToEffectThread(rgbStrip,restoredEffect) | ||||
|             else:                      | ||||
|                 print("stripname in rememberRGBStripEffectThreads -> create new effect") | ||||
|                  | ||||
|                 effectParamValueList: list = [] | ||||
|                 for x in range(len(restoredEffect.effectParameterValues)): | ||||
|                     valdict: dict = {} | ||||
|                     for y in range(len(restoredEffect.effectParameterValues[x])): | ||||
|                         valdict[y] = restoredEffect.effectParameterValues[x][y] | ||||
|                     effectParamValueList.append([x,valdict]) | ||||
|                 self.startEffect(restoredEffect.__class__,[rgbStrip],effectParamValueList) | ||||
|             self.rememberRGBStripEffectThreads.pop(rgbStrip.STRIP_NAME) | ||||
|             | ||||
|              | ||||
|         else: | ||||
|             print("stripname was not in rememberRGBStripEffectThreads") | ||||
|             self.offEffectThreadObject.addRGBStrip(rgbStrip) | ||||
|         self.noticeControllerChange() | ||||
| 
 | ||||
|     def onRGBStripUnRegistered(self,rgbStrip: RGBStrip): | ||||
|         ''' | ||||
|         cycle throught all effectThreadss and  | ||||
|         remove Strip from effect if added | ||||
|         ''' | ||||
|         et: BaseEffect | ||||
|         for et in self.effectThreads: | ||||
|             if rgbStrip in et.effectRGBStrips(): | ||||
|                 et.removeRGBStrip(rgbStrip) | ||||
|         # if the effectThread has no more strips, we stop it and remove it. | ||||
|         for x, effectThread in enumerate(self.effectThreads): | ||||
|             # but ignore the first effectthread, since that is our offeffect that should never be killed | ||||
|             if len(effectThread.effectRGBStrips()) == 0 and x is not 0: | ||||
|                 effectThread.stopEffect() | ||||
|                 self.effectThreads.remove(effectThread) | ||||
|         self.noticeControllerChange() | ||||
| 
 | ||||
|     def updateFttValues(self,ftt: tuple): | ||||
|         ''' TODO this is a themorary funtion util a recorderController is build''' | ||||
|         effectThread: BaseEffect | ||||
|         for effectThread in self.effectThreads: | ||||
|             effectThread.updateFttValues(ftt) | ||||
|     | ||||
|     class EffectGuardian(threading.Thread): | ||||
|         ''' | ||||
|         a bit of failover handling, remove dead threads from effectThread array | ||||
|         move strips without an effect to the offEffect | ||||
| 
 | ||||
|         This Guardian detects Effect Threads that are killed in some unnormal way | ||||
|         This is not the procedere how effects are stoped | ||||
|         Something went wrong when the guarian is removing dead threads! | ||||
|         ''' | ||||
|         def __init__(self, effectController): | ||||
|             threading.Thread.__init__(self, name='EffectGuardian') | ||||
|              | ||||
|             self.effectController = effectController | ||||
|             self.stopped = False | ||||
| 
 | ||||
|         def run(self): | ||||
|             while not self.stopped: | ||||
|                 for effectThread in self.effectController.effectThreads:                         | ||||
|                     # if Thread was killed by something else, we remove it from the list | ||||
|                     if not effectThread.isAlive(): | ||||
|                         for rgbStrip in effectThread.effectRGBStrips(): | ||||
|                             self.effectController.moveRGBStripToEffectThread(rgbStrip,self.effectController.offEffectThreadObject) | ||||
|                         self.effectController.effectThreads.remove(effectThread) | ||||
|                         print("effectController:effectGuardian removed dead Thread " + | ||||
|                               str(effectThread) + ". There must be an error in code!") | ||||
|                         self.effectController.noticeControllerChange() | ||||
|                 time.sleep(1) | ||||
| 
 | ||||
|         def stop(self): | ||||
|             self.stopped = True | ||||
| @ -1,6 +1,6 @@ | ||||
| import threading | ||||
| 
 | ||||
| class effectParameter(object): | ||||
| class EffectParameter(object): | ||||
|     # The Name and the Description of the EffectParameter,  | ||||
|     # should be overwritten by the inheritancing EffectParameter | ||||
|     name="Undefined" | ||||
| @ -12,7 +12,7 @@ class effectParameter(object): | ||||
|     #   [min/off,max/on,current,"description"], | ||||
|     #   [min/off,max/on,current,"description"], | ||||
|     # ] | ||||
|     options = [] | ||||
|     options: list = [] | ||||
| 
 | ||||
|     def __init__(self,name,desc,initOptions = []): | ||||
|         self.name = name | ||||
| @ -27,7 +27,7 @@ class effectParameter(object): | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
| class colorpicker(effectParameter): | ||||
| class colorpicker(EffectParameter): | ||||
|     name="UndefinedColorpicker" | ||||
|     desc="No Description" | ||||
|     type="colorpicker" | ||||
| @ -36,7 +36,7 @@ class colorpicker(effectParameter): | ||||
|     def testValue(self,index,value): | ||||
|         return True | ||||
| 
 | ||||
| class slider(effectParameter): | ||||
| class slider(EffectParameter): | ||||
|     name="UndefinedSlider" | ||||
|     desc="No Description" | ||||
|     type="slider" | ||||
| @ -11,14 +11,13 @@ | ||||
| 
 | ||||
| 
 | ||||
| import numpy | ||||
| import scipy | ||||
| import pyaudio | ||||
| import threading | ||||
| 
 | ||||
| import time | ||||
| 
 | ||||
| 
 | ||||
| class pyAudioRecorder: | ||||
| class PyAudioRecorder: | ||||
|     """Simple, cross-platform class to record from the default input device.""" | ||||
| 
 | ||||
|     def __init__(self): | ||||
| @ -1,16 +1,19 @@ | ||||
| from rgbUtils.debug import debug | ||||
| import uuid | ||||
| import typing | ||||
| 
 | ||||
| class RGBStrip: | ||||
|     # name = the name off the the strip, defined by the client connecting to the server | ||||
|     # uid = unique id, if the strip sends one, use this (later maybe, or never, whatever) | ||||
|     # lenght = the lenght off the strip, for future use of eg WS2812b strips, will be 1 by default | ||||
|     def __init__(self,name,onValuesUpdateHandler,lenght=1): | ||||
|     STRIP_NAME: str | ||||
|     STRIP_LENGHT: int | ||||
|     def __init__(self,name: str,onValuesUpdateHandler: object,lenght: int=1,address: typing.Tuple[str,int] = ("0.0.0.0",0000)): | ||||
|         # UID should be updateable later, or not? | ||||
|         # when updating, be sure it does not exist | ||||
|         self.STRIP_UID = str(uuid.uuid4()) | ||||
|         self.STRIP_NAME = name | ||||
|         self.STRIP_LENGHT = lenght | ||||
|         self.address = address | ||||
| 
 | ||||
|         self.onValuesUpdateHandler = onValuesUpdateHandler | ||||
| 
 | ||||
| @ -18,7 +21,7 @@ class RGBStrip: | ||||
|         self.green = [0]*self.STRIP_LENGHT | ||||
|         self.blue = [0]*self.STRIP_LENGHT | ||||
|      | ||||
|     def RGB(self,red,green,blue,brightness = 100): | ||||
|     def RGB(self,red: int,green: int,blue: int,brightness: int = 100): | ||||
|          | ||||
|         if(red < 0): | ||||
|             red = 0 | ||||
| @ -89,7 +92,6 @@ class RGBStrip: | ||||
|         self.onValuesUpdateHandler(self) | ||||
| 
 | ||||
|     def getData(self): | ||||
|         self.hasNewData = False | ||||
|         return [self.red,self.green,self.blue] | ||||
| 
 | ||||
| 
 | ||||
| @ -1,15 +1,20 @@ | ||||
| from rgbUtils.RGBStrip import RGBStrip | ||||
| from Utils.RGBStrip import RGBStrip | ||||
| import time | ||||
| import threading | ||||
| import json | ||||
| class rgbStripController(): | ||||
| class RGBStripController: | ||||
|     ''' | ||||
|     rgbStrips register themselves at the rgbStripContoller | ||||
|     the rgbStripController calls the backend Provider's onChange function | ||||
|     when there are new values for the strip | ||||
|     ''' | ||||
|     def __init__(self): | ||||
|         #threading.Thread.__init__(self) | ||||
|         self.rgbStrips = [] | ||||
|         self.onRGBStripRegisteredHandler = [] | ||||
|         self.onRGBStripUnRegisteredHandler = [] | ||||
| 
 | ||||
|     def registerRGBStrip(self,rgbStripName,onValuesUpdateHandler,ledcount=1): | ||||
|     def registerRGBStrip(self,rgbStripName: str,onValuesUpdateHandler: object,ledcount=1): | ||||
|         # maybe we can use an unique id if the strip reconnects later, eg push the uid | ||||
|         # to the client on first connect and if he reconnects he sould send it back again. | ||||
|         # the wmos could use the mac adress, if there is a python script it can save the uid | ||||
| @ -1,183 +0,0 @@ | ||||
| # import offEffect | ||||
| from effects.offEffect import offEffect | ||||
| 
 | ||||
| from rgbUtils.debug import debug | ||||
| 
 | ||||
| from rgbUtils.BaseEffect import BaseEffect | ||||
| from rgbUtils.RGBStrip import RGBStrip | ||||
| 
 | ||||
| import time | ||||
| import threading | ||||
| import os | ||||
| import sys | ||||
| 
 | ||||
| # | ||||
| # handles all the effects: | ||||
| # - start/stop effects | ||||
| # - changes parameters of specific effects | ||||
| # - moves the rgbStrips to the effects | ||||
| # - runs a guardian that detects dead effectThreads and moves Strips to offEffect | ||||
| # | ||||
| class effectController: | ||||
| 
 | ||||
|     # list of current running effects | ||||
|     effectThreads = [] | ||||
| 
 | ||||
|     offEffectThreadObject = None | ||||
| 
 | ||||
|     # maybe i will seperate this later | ||||
|     onControllerChangeHandler = [] | ||||
| 
 | ||||
|     def __init__(self,rgbStripController): | ||||
|         self.rgbStripController = rgbStripController | ||||
|         # load the effects | ||||
|         self.effectsList = self.getEffectsListFromDir() | ||||
|         # start the offEffect by default | ||||
|         self.offEffectThreadObject = self.startEffect(offEffect,[]) | ||||
|          | ||||
|         # - a bit of failover handling, remove dead threads from effectThread array | ||||
|         # - move strips without an effect to the offEffect | ||||
|         self.effectGuardian = self.effectGuardian(self) | ||||
|         self.effectGuardian.start() | ||||
| 
 | ||||
|     # starts a effect by given class, rgbStrips and params ([[index,[param,param,param]],[index,[param,param,param]]]) | ||||
|     def startEffect(self, effectClass: BaseEffect, rgbStrips: list, params: list = []): | ||||
| 
 | ||||
|         newEffect = effectClass() | ||||
|         if len(self.effectThreads) > 0 and len(rgbStrips) > 0 or len(self.effectThreads) == 0: | ||||
|             newEffect.start() | ||||
|             self.updateEffectParameters(newEffect, params) | ||||
|             self.effectThreads.append(newEffect) | ||||
| 
 | ||||
|             for rgbStrip in rgbStrips: | ||||
|                 self.moveRGBStripToEffectThread(rgbStrip, newEffect) | ||||
|              | ||||
|         self.noticeControllerChange() | ||||
|         return newEffect | ||||
| 
 | ||||
|     # returns all effectClasses but offEffect, since offEffect will never be killed | ||||
|     # and should not be running twice | ||||
|     def getEffects(self): | ||||
|         # alle außer offEffect | ||||
|         return self.effectsList | ||||
| 
 | ||||
|     # returns all running effectThreads | ||||
|     def getEffectThreads(self): | ||||
|         return self.effectThreads | ||||
|          | ||||
|     # returns a list of the RGBStrips used by this effect | ||||
|     def getEffectRGBStrips(self, effectThreadObject: BaseEffect): | ||||
|         return effectThreadObject.effectRGBStrips() | ||||
| 
 | ||||
|     # move a rgbStip to a running effectThread | ||||
|     def moveRGBStripToEffectThread(self, rgbStrip: RGBStrip, effectThreadObject: BaseEffect): | ||||
|         # cycle throught all effects and  | ||||
|         # remove Strip from effect if added | ||||
|         for et in self.effectThreads: | ||||
|             if rgbStrip in et.effectRGBStrips(): | ||||
|                 et.removeRGBStrip(rgbStrip) | ||||
|         if effectThreadObject.isAlive(): | ||||
|             effectThreadObject.addRGBStrip(rgbStrip) | ||||
|         # check if any effectThread has no more rgbStrips and if so, stop it | ||||
| 
 | ||||
|         # if the effectThread has no more strips, we stop it and remove it. | ||||
|         for x, effectThread in enumerate(self.effectThreads): | ||||
|             if len(effectThread.effectRGBStrips()) == 0 and x is not 0: | ||||
|                 effectThread.stopEffect() | ||||
|                 self.effectThreads.remove(effectThread) | ||||
|         self.noticeControllerChange() | ||||
|          | ||||
|     # updates parameter of a running effectThread | ||||
|     def updateEffectParameters(self, effectThreadObject: BaseEffect, effectParameters): | ||||
|         for effectParameter in effectParameters: | ||||
|             effectThreadObject.updateEffectParameterValues( | ||||
|                 effectParameter[0], effectParameter[1]) | ||||
|         self.noticeControllerChange() | ||||
| 
 | ||||
|     # stops all effectThreads and set the rgbStrips to off | ||||
|     def stopAll(self): | ||||
|         debug("effectController stopAll()") | ||||
|         for effectThread in self.effectThreads: | ||||
|             effectThread.stopEffect() | ||||
|             debug("effectController killed "+str(effectThread)) | ||||
| 
 | ||||
|         self.effectGuardian.stop() | ||||
| 
 | ||||
|         time.sleep(0.5) | ||||
|         # GPIO.cleanup() | ||||
| 
 | ||||
|     # inform the controllerChangeHandler to update the client | ||||
|     def noticeControllerChange(self): | ||||
|         for controllerChangeHandler in self.onControllerChangeHandler: | ||||
|             controllerChangeHandler() | ||||
| 
 | ||||
|     # add onControllerChangeHandler | ||||
|     def addOnControllerChangeHandler(self, hander): | ||||
|         print("addOnControllerChangeHandler", str(hander)) | ||||
|         self.onControllerChangeHandler.append(hander) | ||||
|         # send data to this client | ||||
|         hander() | ||||
| 
 | ||||
|     # remove onControllerChangeHandler | ||||
|     def removeOnControllerChangeHandler(self, hander): | ||||
|         print("removeOnControllerChangeHandler", str(hander)) | ||||
|         if hander in self.onControllerChangeHandler: | ||||
|             self.onControllerChangeHandler.remove(hander) | ||||
|         else: | ||||
|             print('\n\n -> client was never registered!') | ||||
| 
 | ||||
|     # automaticly loads all modules from effects subdir and adds them to the list of effects if they have the BaseEffect as subclass  | ||||
|     def getEffectsListFromDir(self): | ||||
|         effectsList = [] | ||||
|         for raw_module in os.listdir(os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__), os.pardir),"effects"))): | ||||
|              | ||||
|             if raw_module == '__init__.py' or raw_module == 'offEffect.py' or raw_module[-3:] != '.py': | ||||
|                 continue | ||||
|             effectModule = __import__("effects."+raw_module[:-3], fromlist=[raw_module[:-3]]) | ||||
|             effectClass = getattr(effectModule, raw_module[:-3]) | ||||
|             if issubclass(effectClass,BaseEffect): | ||||
|                 effectsList.append(effectClass) | ||||
|         print("Loaded effects: ",effectsList) | ||||
|         return effectsList | ||||
| 
 | ||||
|     def onRGBStripRegistered(self,rgbStrip): | ||||
|         self.offEffectThreadObject.addRGBStrip(rgbStrip) | ||||
|         self.noticeControllerChange() | ||||
| 
 | ||||
|     def onRGBStripUnRegistered(self,rgbStrip): | ||||
|         # cycle throught all effects and  | ||||
|         # remove Strip from effect if added | ||||
|         for et in self.effectThreads: | ||||
|             if rgbStrip in et.effectRGBStrips(): | ||||
|                 et.removeRGBStrip(rgbStrip) | ||||
|         # if the effectThread has no more strips, we stop it and remove it. | ||||
|         for x, effectThread in enumerate(self.effectThreads): | ||||
|             if len(effectThread.effectRGBStrips()) == 0 and x is not 0: | ||||
|                 effectThread.stopEffect() | ||||
|                 self.effectThreads.remove(effectThread) | ||||
|         self.noticeControllerChange() | ||||
| 
 | ||||
|     # - a bit of failover handling, remove dead threads from effectThread array | ||||
|     # - move strips without an effect to the offEffect | ||||
|     class effectGuardian(threading.Thread): | ||||
|         def __init__(self, effectController): | ||||
|             threading.Thread.__init__(self, name='effectGuardian') | ||||
|              | ||||
|             self.effectController = effectController | ||||
|             self.stopped = False | ||||
| 
 | ||||
|         def run(self): | ||||
|             while not self.stopped: | ||||
|                 for effectThread in self.effectController.effectThreads:                         | ||||
|                     # if Thread was killed by something else, we remove it from the list | ||||
|                     if not effectThread.isAlive(): | ||||
|                         for rgbStrip in effectThread.effectRGBStrips(): | ||||
|                             self.effectController.moveRGBStripToEffectThread(rgbStrip,self.effectController.offEffectThreadObject) | ||||
|                         self.effectController.effectThreads.remove(effectThread) | ||||
|                         print("effectController:effectGuardian removed dead Thread " + | ||||
|                               str(effectThread) + ". There must be an error in code!") | ||||
|                         self.effectController.noticeControllerChange() | ||||
|                 time.sleep(1) | ||||
| 
 | ||||
|         def stop(self): | ||||
|             self.stopped = True | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user