示例#1
0
文件: mixer.py 项目: tibbon/firemix
    def render_command_list(self, list, buffer):
        """
        Renders the output of a command list to the output buffer.
        Commands are rendered in FIFO overlap style.  Run the list through
        filter_and_sort_commands() beforehand.
        If the output buffer is not zero (black) at a command's target,
        the output will be additively blended according to the blend_state
        (0.0 = 100% original, 1.0 = 100% new)
        """
        for command in list:
            color = command.get_color()
            if isinstance(command, SetAll):
                buffer[:,:] = color

            elif isinstance(command, SetStrand):
                strand = command.get_strand()
                start, end = BufferUtils.get_strand_extents(strand)
                buffer[start:end] = color

            elif isinstance(command, SetFixture):
                pass
                # strand = command.get_strand()
                # fixture = command.get_address()
                # start = BufferUtils.logical_to_index((strand, fixture, 0))
                # end = start + self._scene.fixture(strand, fixture).pixels
                # buffer[start:end] = color

            elif isinstance(command, SetPixel):
                strand = command.get_strand()
                fixture = command.get_address()
                offset = command.get_pixel()
                pixel = BufferUtils.logical_to_index((strand, fixture, offset))
                buffer[pixel] = color
示例#2
0
    def render_command_list(self, list, buffer):
        """
        Renders the output of a command list to the output buffer.
        Commands are rendered in FIFO overlap style.  Run the list through
        filter_and_sort_commands() beforehand.
        If the output buffer is not zero (black) at a command's target,
        the output will be additively blended according to the blend_state
        (0.0 = 100% original, 1.0 = 100% new)
        """
        for command in list:
            color = command.get_color()
            if isinstance(command, SetAll):
                buffer[:, :] = color

            elif isinstance(command, SetStrand):
                strand = command.get_strand()
                start, end = BufferUtils.get_strand_extents(strand)
                buffer[start:end] = color

            elif isinstance(command, SetFixture):
                strand = command.get_strand()
                fixture = command.get_address()
                start = BufferUtils.logical_to_index((strand, fixture, 0))
                end = start + self._scene.fixture(strand, fixture).pixels
                buffer[start:end] = color

            elif isinstance(command, SetPixel):
                strand = command.get_strand()
                fixture = command.get_address()
                offset = command.get_pixel()
                pixel = BufferUtils.logical_to_index((strand, fixture, offset))
                buffer[pixel] = color
示例#3
0
    def _write_legacy(self, buf, strand_settings, clients):
        packets = []

        if 'legacy' not in self._packet_cache:
            self._packet_cache['legacy'] = [None] * len(strand_settings)

        for strand in range(len(strand_settings)):
            if not strand_settings[strand]["enabled"]:
                continue

            start, end = BufferUtils.get_strand_extents(strand)
            start *= 3
            end *= 3

            packet_header_size = 4
            packet_size = (end - start) + packet_header_size

            packet = self._packet_cache['legacy'][strand]
            if packet is None:
                packet = np.zeros(packet_size, dtype=np.int8)
                self._packet_cache['legacy'][strand] = packet

            length = packet_size - packet_header_size

            packet[0] = ord('S')
            packet[1] = strand
            packet[2] = length & 0x00FF
            packet[3] = (length & 0xFF00) >> 8

            np.copyto(packet[packet_header_size:], buf[start:end])
            packets.append(packet)

        for client in clients:
            try:
                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"]))
            except socket.gaierror:
                print("Bad hostname: ", client["host"])
                continue
            except:
                continue
示例#4
0
    def _write_legacy(self, buf, strand_settings, clients):
        packets = []

        if 'legacy' not in self._packet_cache:
            self._packet_cache['legacy'] = [None] * len(strand_settings)

        for strand in range(len(strand_settings)):
            if not strand_settings[strand]["enabled"]:
                continue

            start, end = BufferUtils.get_strand_extents(strand)
            start *= 3
            end *= 3

            packet_header_size = 4
            packet_size = (end-start) + packet_header_size

            packet = self._packet_cache['legacy'][strand]
            if packet is None:
                packet = np.zeros(packet_size, dtype=np.int8)
                self._packet_cache['legacy'][strand] = packet

            length = packet_size - packet_header_size

            packet[0] = ord('S')
            packet[1] = strand
            packet[2] = length & 0x00FF
            packet[3] = (length & 0xFF00) >> 8

            np.copyto(packet[packet_header_size:], buf[start:end])
            packets.append(packet)

        for client in clients:
            try:
                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"]))
            except socket.gaierror:
                print("Bad hostname: ", client["host"])
                continue
            except:
                continue
示例#5
0
    def write(self, buffer):
        """
        Performs a bulk strand write.
        Decodes the HLS-Float data according to client settings
        """
        strand_settings = self._app.scene.get_strand_settings()

        # Hack: assume that at least one client will be RGB mode
        intbuffer = np.int_(buffer * cache_steps)
        alldata = [getRGB(*pixel) for pixel in intbuffer]
        alldata = [item for sublist in alldata for item in sublist]

        for client in [client for client in self._app.settings['networking']['clients'] if client["enabled"]]:
            # TODO: Split into smaller packets so that less-than-ideal networks will be OK
            packet = array.array('B', [])
            client_color_mode = client["color-mode"]

            for strand in range(len(strand_settings)):
                if not strand_settings[strand]["enabled"]:
                    continue
                color_mode = strand_settings[strand]["color-mode"]

                start, end = BufferUtils.get_strand_extents(strand)

                if client_color_mode == "RGB8":
                    data = array.array('B', alldata[start*3:end*3])
                else:
                    data = [channel for pixel in buffer[start:end] for channel in pixel]
                    data = array.array('B', struct.pack('%sf' % len(data), *data))

                length = len(data)
                command = COMMAND_SET_RGB if color_mode == "RGB8" else COMMAND_SET_BGR
                packet.extend(array.array('B', [strand, command, (length & 0xFF), (length & 0xFF00) >> 8]))
                packet.extend(data)

# Is the strand packing above slow? I wonder...
# Does it mean anything if this is faster?
#            length = len(alldata)
#            packet.extend(array.array('B', [0, 0, (length & 0xFF), (length & 0xFF00) >> 8]))
#            packet.extend(array.array('B', alldata))

            self._socket.sendto(packet, (client["host"], client["port"]))
示例#6
0
def render_command_list(scene, list, buffer):
    """
    Renders the output of a command list to the output buffer.
    Commands are rendered in FIFO overlap style.  Run the list through
    filter_and_sort_commands() beforehand.
    If the output buffer is not zero (black) at a command's target,
    the output will be additively blended according to the blend_state
    (0.0 = 100% original, 1.0 = 100% new)
    """

    for command in list:
        color = command.get_color()
        if isinstance(command, SetAll):
            buffer[:,:] = color

        elif isinstance(command, SetStrand):
            strand = command.get_strand()
            start, end = BufferUtils.get_strand_extents(strand)
            buffer[start:end] = color

        elif isinstance(command, SetFixture):
            strand = command.get_strand()
            address = command.get_address()
            fixture = scene.fixture(strand, address)

            if fixture is None:
                log.error("SetFixture command setting invalid fixture: %s", (strand,address))
                continue

            start = BufferUtils.logical_to_index((strand, address, 0))
            end = start + fixture.pixels
            buffer[start:end] = color

        elif isinstance(command, SetPixel):
            strand = command.get_strand()
            address = command.get_address()
            offset = command.get_pixel()
            pixel = BufferUtils.logical_to_index((strand, address, offset))
            buffer[pixel] = color
示例#7
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:
示例#8
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:
示例#9
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"]))
示例#10
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"]))