import blinkenbase.blinkenfoo as blinkenfoo from blinkenbase.Color import Color class Blinkenroom: def __init__(self, p_device_list, p_fps = 42): self.fps = p_fps self.device_list = p_device_list self._calc_total_length() self._generate_index_map() self.previous_device = None self._remove_unreachable_devices() ##################### ###private methods### ##################### def _remove_unreachable_devices(self): """ Removes devices that are not reachable from the devices list """ for device in self.device_list: if not device.is_reachable(): print(device.name + " is not available") del self.device_list[self.device_list.index(device)] def _calc_total_length(self): self.total_length = 0 for device in self.device_list: self.total_length += device.length return self.total_length def _generate_index_map(self): self.global_map = [0 for _ in range(self.total_length)] current_index = 0 for device in self.device_list: for i in range(device.length): self.global_map[current_index + i] = device current_index += device.length #################### ###public methods### #################### def set_brightness(self, p_level=100): """ Sets the brightness of every blinkendevice in this blinkenroom. Max is 100, min 0 """ for device in self.device_list: device.brightness_factor = p_level def send_frame(self, p_frame, p_offset = 0): """ Sends an whole frame to all blinkenfoo devices. The frames length has to match all blinkenfoos length combined. """ frame_length = len(p_frame) #TODO Make this more efficient -> use blinkenfoo's send_frame, dont send #a frame pixel wise, as every single pixel has to be mapped to a #blinkenfoo if not frame_length == self.total_length: raise ValueError("Frame length does not match total length: Given %d, expected %d" % (frame_length, self.total_length)) for i in range(frame_length): current_index = (i + p_offset) % frame_length pixel = p_frame[current_index] self.set_pixel(i, pixel) self.flush() def set_full_color(self, p_color): """ Sets all blinkenfoo to the given color. """ for device in self.device_list: device.set_full_color(p_color) def set_pixel(self, p_index, p_color): """ Sets a single pixel. The index is mapped to a blinkenfoo in the blinkenroom. """ device = self.global_map[p_index] if device == None: raise ValueError("Index is not mapped to any device (out of range)") # Mapping index to device # (Substracting foregone device length) for i in range(len(self.device_list)): current_device = self.device_list[i] if current_device == device: break p_index -= current_device.length device.set_pixel(p_index, p_color) def flush(self, p_reset=False): """ Flushes the changes made in the buffer (blinkefoo buffers, a blinkenroom has no buffer). """ for device in self.device_list: device.flush(p_reset) def get_device_by_index(self, p_index): """ Returns the blinkenfoo that the given index is mapped on """ if p_index > self.total_length: raise ValueError("Index out of range:%d > %d" % (p_index, self.total_length)) return self.global_map[p_index] def is_overlapping(self, p_blinkeroom): """ Checks wether a blinkenroom's devices overlap with this's devices """ return len(set(self.device_list).intersection(p_blinkeroom.device_list)) is not 0 def get_last_frame(self): """ Returns the buffer of all blinkenfoos concatenated. Does not work if flush(True) is invoked, since this will clear the buffer after sending. """ frame = [] for device in self.device_list: frame += device.buffer return frame def clear(self): for device in self.device_list: device.clear() BLINKENROOM_LOUNGE = Blinkenroom(blinkenfoo.DEVICE_LIST_LOUNGE)