blinkenroom.py 4.06 KiB
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 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
BLINKENROOM_LOUNGE = Blinkenroom(blinkenfoo.DEVICE_LIST_LOUNGE)