def write_buffer(self, buffer): """ Performs a bulk strand write. Decodes the HLS-Float data according to client settings """ strand_settings = self._app.scene.get_strand_settings() clients = [ client for client in self._app.settings['networking']['clients'] if client["enabled"] ] clients_by_type = defaultdict(list) have_non_dimmed = False for c in clients: clients_by_type[c.get("protocol", "Legacy")].append(c) dimmed_legacy_clients = [ c for c in clients_by_type["Legacy"] if not c.get('ignore-dimming') ] undimmed_legacy_clients = [ c for c in clients_by_type["Legacy"] if c.get('ignore-dimming') ] opc_clients = clients_by_type["OPC"] if undimmed_legacy_clients: # Protect against presets or transitions that write float data. buffer_rgb = hls_to_rgb_perceptual(buffer) buffer_rgb_int = np.int8(struct_flat(buffer_rgb) * 255) self._write_legacy(buffer_rgb_int, strand_settings, undimmed_legacy_clients) # Now that we've written to clients that don't want dimmed data, apply # the global dimmer from the mixer and re-convert to RGB if self._app.mixer.global_dimmer < 1.0: buffer['light'] *= self._app.mixer.global_dimmer if self._app.mixer.useColorCorrections: buffer_rgb = hls_to_rgb_perceptual(buffer) else: buffer_rgb = hls_to_rgb(buffer) buffer_rgb_int = np.int8(struct_flat(buffer_rgb) * 255) if dimmed_legacy_clients: self._write_legacy(buffer_rgb_int, strand_settings, dimmed_legacy_clients) if opc_clients: self._write_opc(buffer_rgb_int, strand_settings, opc_clients)
def write_buffer(self, buffer): """ Performs a bulk strand write. Decodes the HLS-Float data according to client settings """ strand_settings = self._app.scene.get_strand_settings() clients = [client for client in self._app.settings['networking']['clients'] if client["enabled"]] clients_by_type = defaultdict(list) have_non_dimmed = False for c in clients: clients_by_type[c.get("protocol", "Legacy")].append(c) dimmed_legacy_clients = [c for c in clients_by_type["Legacy"] if not c.get('ignore-dimming')] undimmed_legacy_clients = [c for c in clients_by_type["Legacy"] if c.get('ignore-dimming')] opc_clients = clients_by_type["OPC"] if undimmed_legacy_clients: # Protect against presets or transitions that write float data. buffer_rgb = hls_to_rgb_perceptual(buffer) buffer_rgb_int = np.int8(struct_flat(buffer_rgb) * 255) self._write_legacy(buffer_rgb_int, strand_settings, undimmed_legacy_clients) # Now that we've written to clients that don't want dimmed data, apply # the global dimmer from the mixer and re-convert to RGB if self._app.mixer.global_dimmer < 1.0: buffer['light'] *= self._app.mixer.global_dimmer if self._app.mixer.useColorCorrections: buffer_rgb = hls_to_rgb_perceptual(buffer) else: buffer_rgb = hls_to_rgb(buffer) buffer_rgb_int = np.int8(struct_flat(buffer_rgb) * 255) if dimmed_legacy_clients: self._write_legacy(buffer_rgb_int, strand_settings, dimmed_legacy_clients) if opc_clients: self._write_opc(buffer_rgb_int, strand_settings, opc_clients)
def write_buffer(self, buffer): """ Performs a bulk strand write. Decodes the HLS-Float data according to client settings """ strand_settings = self._app.scene.get_strand_settings() # Protect against presets or transitions that write float data. buffer_rgb = np.int_(hls_to_rgb(buffer) * 255) def fill_packet(intbuffer, start, end, offset, packet, swap_order=False): for pixel_index, pixel in enumerate(intbuffer[start:end]): buffer_index = offset + pixel_index * 3 if swap_order: packet[buffer_index] = pixel[2] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[0] else: packet[buffer_index] = pixel[0] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[2] clients = [client for client in self._app.settings['networking']['clients'] if client["enabled"]] if not clients: return for strand in xrange(len(strand_settings)): if not strand_settings[strand]["enabled"]: continue packet = array.array('B', []) color_mode = strand_settings[strand]["color-mode"] start, end = BufferUtils.get_strand_extents(strand) packet_header_size = 4 packet_size = (end-start) * 3 + packet_header_size packet = self._packet_cache.get(packet_size, None) if packet is None: packet = [0,] * packet_size self._packet_cache[packet_size] = packet command = COMMAND_SET_RGB if color_mode == "RGB8" else COMMAND_SET_BGR packet[0] = strand packet[1] = command length = packet_size - packet_header_size packet[2] = length & 0x00FF packet[3] = (length & 0xFF00) >> 8 rgb8_packet = None bgr8_packet = None for client in clients: # TODO: Split into smaller packets so that less-than-ideal networks will be OK client_color_mode = client["color-mode"] if client_color_mode == 'RGB8': if rgb8_packet is None: fill_packet(buffer_rgb, start, end, packet_header_size, packet, False) rgb8_packet = array.array('B', packet) packet = rgb8_packet elif client_color_mode == 'BGR8': if bgr8_packet is None: fill_packet(buffer_rgb, start, end, packet_header_size, packet, True) bgr8_packet = array.array('B', packet) packet = rgb8_packet else: raise NotImplementedError('Unknown color mode: %s' % client_color_mode) try: #print "Sending packet of length %i for strand %i", (len(packet), strand) self._socket.sendto(packet, (client["host"], client["port"])) except IOError as (errno, strerror): print "I/O error({0}): {1}".format(errno, strerror) #print "On strand %i with length %i" % (strand, len(packet)) except ValueError: print "Could not convert data to an integer." except:
def write_buffer(self, buffer): """ Performs a bulk strand write. Decodes the HLS-Float data according to client settings """ strand_settings = self._app.scene.get_strand_settings() # Protect against presets or transitions that write float data. buffer_rgb = np.int_(hls_to_rgb(buffer) * 255) def fill_packet(intbuffer, start, end, offset, packet, swap_order=False): for pixel_index, pixel in enumerate(intbuffer[start:end]): buffer_index = offset + pixel_index * 3 if swap_order: packet[buffer_index] = pixel[2] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[0] else: packet[buffer_index] = pixel[0] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[2] clients = [ client for client in self._app.settings['networking']['clients'] if client["enabled"] ] if not clients: return for strand in xrange(len(strand_settings)): if not strand_settings[strand]["enabled"]: continue packet = array.array('B', []) color_mode = strand_settings[strand]["color-mode"] start, end = BufferUtils.get_strand_extents(strand) packet_header_size = 4 packet_size = (end - start) * 3 + packet_header_size packet = self._packet_cache.get(packet_size, None) if packet is None: packet = [ 0, ] * packet_size self._packet_cache[packet_size] = packet command = COMMAND_SET_RGB if color_mode == "RGB8" else COMMAND_SET_BGR packet[0] = strand packet[1] = command length = packet_size - packet_header_size packet[2] = length & 0x00FF packet[3] = (length & 0xFF00) >> 8 rgb8_packet = None bgr8_packet = None for client in clients: # TODO: Split into smaller packets so that less-than-ideal networks will be OK client_color_mode = client["color-mode"] if client_color_mode == 'RGB8': if rgb8_packet is None: fill_packet(buffer_rgb, start, end, packet_header_size, packet, False) rgb8_packet = array.array('B', packet) packet = rgb8_packet elif client_color_mode == 'BGR8': if bgr8_packet is None: fill_packet(buffer_rgb, start, end, packet_header_size, packet, True) bgr8_packet = array.array('B', packet) packet = rgb8_packet else: raise NotImplementedError('Unknown color mode: %s' % client_color_mode) try: #print "Sending packet of length %i for strand %i", (len(packet), strand) self._socket.sendto(packet, (client["host"], client["port"])) except IOError as (errno, strerror): print "I/O error({0}): {1}".format(errno, strerror) #print "On strand %i with length %i" % (strand, len(packet)) except ValueError: print "Could not convert data to an integer." except:
def write_buffer(self, buffer): """ Performs a bulk strand write. Decodes the HLS-Float data according to client settings """ strand_settings = self._app.scene.get_strand_settings() clients = [ client for client in self._app.settings['networking']['clients'] if client["enabled"] ] clients_by_type = defaultdict(list) have_non_dimmed = False for c in clients: clients_by_type[c.get("protocol", "Legacy")].append(c) have_non_dimmed = c.get("ignore-dimming", False) if not have_non_dimmed else True have_zmq_clients = bool(clients_by_type.get("ZMQ", [])) legacy_clients = clients_by_type["Legacy"] opc_clients = clients_by_type["OPC"] # Apply the global dimmer from the mixer. # TODO: this is stupid. Should just pass the global dimmer as metadata to the clients if have_non_dimmed: non_dimmed_buffer = deepcopy(buffer) if self._app.mixer.global_dimmer < 1.0: buffer.T[1] *= self._app.mixer.global_dimmer # Protect against presets or transitions that write float data. buffer_rgb = np.int_(hls_to_rgb(buffer) * 255) np.clip(buffer_rgb, 0, 255, buffer_rgb) if have_non_dimmed: non_dimmed_buffer_rgb = np.int_( hls_to_rgb(non_dimmed_buffer) * 255) np.clip(non_dimmed_buffer_rgb, 0, 255, non_dimmed_buffer_rgb) def fill_packet(intbuffer, start, end, offset, packet, swap_order=False): for pixel_index, pixel in enumerate(intbuffer[start:end]): buffer_index = offset + pixel_index * 3 if swap_order: packet[buffer_index] = pixel[2] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[0] else: packet[buffer_index] = pixel[0] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[2] packets = [] non_dimmed_packets = [] for strand in xrange(len(strand_settings)): if not strand_settings[strand]["enabled"]: continue start, end = BufferUtils.get_strand_extents(strand) packet_header_size = 4 packet_size = (end - start) * 3 + packet_header_size try: packet = self._packet_cache[packet_size] except KeyError: packet = [ 0, ] * packet_size self._packet_cache[packet_size] = packet length = packet_size - packet_header_size packet[0] = ord('S') packet[1] = strand packet[2] = length & 0x00FF packet[3] = (length & 0xFF00) >> 8 fill_packet(buffer_rgb, start, end, packet_header_size, packet, False) packets.append(array.array('B', packet)) if have_non_dimmed: fill_packet(non_dimmed_buffer_rgb, start, end, packet_header_size, packet, False) non_dimmed_packets.append(array.array('B', packet)) if USE_ZMQ and have_zmq_clients: frame = ["B"] + packets + ["E"] self.socket.send_multipart(frame) for client in legacy_clients: self.socket.sendto(array.array('B', [ord('B')]), (client["host"], client["port"])) for packet in (non_dimmed_packets if client.get( "ignore-dimming", False) else packets): self.socket.sendto(packet, (client["host"], client["port"])) time.sleep(0.001) self.socket.sendto(array.array('B', [ord('E')]), (client["host"], client["port"])) for client in opc_clients: # TODO: This is hacky, but for now we re-write the packet for OPC here... # Fortunately, OPC happens to look a lot like our existing protocol... # Byte 0 is channel (aka strand). 0 is broadcast address, indexing starts at 1. # Byte 1 is command, always 0 for "set pixel colors" # Bytes 2 and 3 are big-endian length of the data block. # Note: LEDScape needs the strands all concatenated together which is annoying packet[0] = packet[1] + 1 tpacket = [0x00, 0x00, 0x00, 0x00] for packet in packets: tpacket += packet[4:] tlen = len(tpacket) - 4 tpacket[2] = (tlen & 0xFF00) >> 8 tpacket[3] = (tlen & 0xFF) tpacket = array.array('B', tpacket) self.socket.sendto(tpacket, (client["host"], client["port"]))
def write_buffer(self, buffer): """ Performs a bulk strand write. Decodes the HLS-Float data according to client settings """ strand_settings = self._app.scene.get_strand_settings() clients = [client for client in self._app.settings['networking']['clients'] if client["enabled"]] clients_by_type = defaultdict(list) for c in clients: clients_by_type[c.get("protocol", "Legacy")].append(c) have_zmq_clients = bool(clients_by_type.get("ZMQ", [])) legacy_clients = clients_by_type["Legacy"] opc_clients = clients_by_type["OPC"] # Protect against presets or transitions that write float data. buffer_rgb = np.int_(hls_to_rgb(buffer) * 255) np.clip(buffer_rgb, 0, 255, buffer_rgb) def fill_packet(intbuffer, start, end, offset, packet, swap_order=False): for pixel_index, pixel in enumerate(intbuffer[start:end]): buffer_index = offset + pixel_index * 3 if swap_order: packet[buffer_index] = pixel[2] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[0] else: packet[buffer_index] = pixel[0] packet[buffer_index + 1] = pixel[1] packet[buffer_index + 2] = pixel[2] packets = [] for strand in xrange(len(strand_settings)): if not strand_settings[strand]["enabled"]: continue start, end = BufferUtils.get_strand_extents(strand) packet_header_size = 4 packet_size = (end-start) * 3 + packet_header_size try: packet = self._packet_cache[packet_size] except KeyError: packet = [0,] * packet_size self._packet_cache[packet_size] = packet length = packet_size - packet_header_size packet[0] = ord('S') packet[1] = strand packet[2] = length & 0x00FF packet[3] = (length & 0xFF00) >> 8 fill_packet(buffer_rgb, start, end, packet_header_size, packet, False) packets.append(array.array('B', packet)) if USE_ZMQ and have_zmq_clients: frame = ["B"] + packets + ["E"] self.socket.send_multipart(frame) for client in legacy_clients: self.socket.sendto(array.array('B', [ord('B')]), (client["host"], client["port"])) for packet in packets: self.socket.sendto(packet, (client["host"], client["port"])) self.socket.sendto(array.array('B', [ord('E')]), (client["host"], client["port"])) for client in opc_clients: # TODO: This is hacky, but for now we re-write the packet for OPC here... # Fortunately, OPC happens to look a lot like our existing protocol... # Byte 0 is channel (aka strand). 0 is broadcast address, indexing starts at 1. # Byte 1 is command, always 0 for "set pixel colors" # Bytes 2 and 3 are big-endian length of the data block. # Note: LEDScape needs the strands all concatenated together which is annoying packet[0] = packet[1] + 1 tpacket = [0x00, 0x00, 0x00, 0x00] for packet in packets: tpacket += packet[4:] tlen = len(tpacket) - 4 tpacket[2] = (tlen & 0xFF00) >> 8 tpacket[3] = (tlen & 0xFF) tpacket = array.array('B', tpacket) self.socket.sendto(tpacket, (client["host"], client["port"]))