Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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:
Example #4
0
    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:
Example #5
0
    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"]))
Example #6
0
    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"]))