def reset_output_buffers(self): """ Clears the output buffers """ self._buffer_a = BufferUtils.create_buffer() self._buffer_b = BufferUtils.create_buffer() self._output_buffer = BufferUtils.create_buffer()
def _spawn(self, current_strand, current_fixture, population): children = set() neighbors = self.pattern.scene().get_pixel_neighbors(self.loc) neighbors = [BufferUtils.index_to_logical(n) for n in neighbors] random.shuffle(neighbors) # Iterate over candidate pixels that aren't on the current fixture candidates = [ n for n in neighbors if n[:2] != (current_strand, current_fixture) ] for candidate in candidates: child_index = BufferUtils.logical_to_index(candidate) if len(children) == 0: # Spawn at least one new dragon to replace the old one. This first one skips the growth. dir = 1 if candidate[2] == 0 else -1 child = _Dragon(self.pattern, child_index, dir, self.pattern._current_time) child.growing = False child.alive = True children.add(child) population += 1 elif (population < self.pattern.parameter('pop-limit').get() and random.random() < self.pattern.parameter('birth-rate').get()): # Randomly spawn new dragons dir = 1 if candidate[2] == 0 else -1 child = _Dragon(self.pattern, child_index, dir, self.pattern._current_time) children.add(child) population += 1 return children
def get_pixel_neighbors(self, index): """ Returns a list of pixel addresses that are adjacent to the given address. """ neighbors = self._pixel_neighbors_cache.get(index, None) if neighbors is None: neighbors = [] strand, address, pixel = BufferUtils.index_to_logical(index) f = self.fixture(strand, address) neighbors = [BufferUtils.logical_to_index((strand, address, p)) for p in f.pixel_neighbors(pixel)] if (pixel == 0) or (pixel == f.pixels - 1): # If this pixel is on the end of a fixture, consider the neighboring fixtures loc = 'end' if pixel == 0: loc = 'start' logical_neighbors = self.get_colliding_fixtures(strand, address, loc) neighbors += [BufferUtils.logical_to_index(n) for n in logical_neighbors] self._pixel_neighbors_cache[index] = neighbors return neighbors
def get_pixel_neighbors(self, index): """ Returns a list of pixel addresses that are adjacent to the given address. """ neighbors = self._pixel_neighbors_cache.get(index, None) if neighbors is None: neighbors = [] strand, address, pixel = BufferUtils.index_to_logical(index) f = self.fixture(strand, address) neighbors = [ BufferUtils.logical_to_index((strand, address, p)) for p in f.pixel_neighbors(pixel) ] if (pixel == 0) or (pixel == f.pixels - 1): # If this pixel is on the end of a fixture, consider the neighboring fixtures loc = 'end' if pixel == 0: loc = 'start' logical_neighbors = self.get_colliding_fixtures( strand, address, loc) neighbors += [ BufferUtils.logical_to_index(n) for n in logical_neighbors ] self._pixel_neighbors_cache[index] = neighbors return neighbors
def setup(self): self.num_strands, self.num_pixels = BufferUtils.get_buffer_size( self._app) self.scene_bb = self._app.scene.get_fixture_bounding_box() self.scene_center = (self.scene_bb[0] + (self.scene_bb[2] - self.scene_bb[0]) / 2, self.scene_bb[1] + (self.scene_bb[3] - self.scene_bb[1]) / 2) dx = self.scene_bb[2] - self.scene_center[0] dy = self.scene_bb[3] - self.scene_center[1] self.scene_radius = sqrt(pow(dx, 2) + pow(dy, 2)) self.locations = self._app.scene.get_all_pixel_locations() self.buffer_addr = {} self.angles = {} self.radii = {} for pixel, location in self.locations: self.buffer_addr[pixel] = BufferUtils.get_buffer_address( self._app, pixel) dy = location[1] - self.scene_center[1] dx = location[0] - self.scene_center[0] angle = (atan2(dy, dx) + pi) / (2.0 * pi) self.radii[pixel] = sqrt(pow(dx, 2) + pow(dy, 2)) self.angles[pixel] = angle
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
def __init__(self, app, name): super(Layer, self).__init__() self._app = app self._mixer = app.mixer self._enable_profiling = self._app.args.profile self.name = name self._playlist = None self._scene = app.scene self._main_buffer = None self._secondary_buffer = None self._in_transition = False self._transition = None self.transition_progress = 0.0 self._start_transition = False self._transition_list = [] self._transition_duration = self._app.settings.get('mixer')['transition-duration'] self._transition_slop = self._app.settings.get('mixer')['transition-slop'] self._elapsed = 0 self._duration = self._app.settings.get('mixer')['preset-duration'] # Load transitions self.set_transition_mode(self._app.settings.get('mixer')['transition']) if not self._scene: pass else: self._main_buffer = BufferUtils.create_buffer() self._secondary_buffer = BufferUtils.create_buffer()
def render(self, start, end, progress, out): start[self.mask] = (0.0, 0.0, 0.0) end[np.invert(self.mask)] = (0.0, 0.0, 0.0) idx = int(progress * len(self.rand_index)) if idx >= self.last_idx: for i in range(self.last_idx, idx): fix = self.fixtures[self.rand_index[i]] self._strobing.append(fix) self._time[fix] = progress self._on[fix] = True else: for i in range(idx, self.last_idx): fix = self.fixtures[self.rand_index[i]] if fix in self._strobing: self._strobing.remove(fix) pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end] = False self._on[fix] = False self.last_idx = idx for fix in self._strobing: pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end] = self._on[fix] self._on[fix] = not self._on[fix] if progress > self._time[fix] + self._duration: self._strobing.remove(fix) self.mask[pix_start:pix_end][:] = True np.add(struct_flat(start), struct_flat(end), struct_flat(out))
def __init__(self, parent, args): QtCore.QThread.__init__(self, parent) self._running = False self.args = args self.settings = Settings() self.net = Networking(self) BufferUtils.set_app(self) self.scene = Scene(self) self.plugins = PluginLoader() self.mixer = Mixer(self) self.playlist = Playlist(self) self.qt_app = parent self.scene.warmup() self.aubio_connector = None if not self.args.noaudio: self.aubio_thread = QtCore.QThread() self.aubio_thread.start() self.aubio_connector = AubioConnector() self.aubio_connector.onset_detected.connect( self.mixer.onset_detected) self.aubio_connector.fft_data.connect( self.mixer.audio.update_fft_data) self.aubio_connector.pitch_data.connect( self.mixer.audio.update_pitch_data) self.aubio_connector.moveToThread(self.aubio_thread) self.mixer.set_playlist(self.playlist) if self.args.preset: log.info("Setting constant preset %s" % args.preset) self.mixer.set_constant_preset(args.preset)
def __init__(self, parent, args): QtCore.QThread.__init__(self, parent) self._running = False self.args = args self.settings = Settings() self.net = Networking(self) BufferUtils.set_app(self) self.scene = Scene(self) self.plugins = PluginLoader() self.mixer = Mixer(self) self.playlist = Playlist(self) self.qt_app = parent self.scene.warmup() self.aubio_connector = None if not self.args.noaudio: self.aubio_thread = QtCore.QThread() self.aubio_thread.start() self.aubio_connector = AubioConnector() self.aubio_connector.onset_detected.connect(self.mixer.onset_detected) self.aubio_connector.fft_data.connect(self.mixer.audio.update_fft_data) self.aubio_connector.pitch_data.connect(self.mixer.audio.update_pitch_data) self.aubio_connector.moveToThread(self.aubio_thread) self.mixer.set_playlist(self.playlist) if self.args.preset: log.info("Setting constant preset %s" % args.preset) self.mixer.set_constant_preset(args.preset)
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() buffer[strand,:] = color elif isinstance(command, SetFixture): strand = command.get_strand() address = command.get_address() _, start = BufferUtils.get_buffer_address(self._app, (strand, address, 0)) end = start + self._scene.fixture(strand, address).pixels buffer[strand,start:end] = color elif isinstance(command, SetPixel): strand = command.get_strand() address = command.get_address() pixel = command.get_pixel() (strand, pixel_offset) = BufferUtils.get_buffer_address(self._app, (strand, address, pixel)) buffer[strand][pixel_offset] = color
def __init__(self, app, name): super(Layer, self).__init__() self._app = app self._mixer = app.mixer self._enable_profiling = self._app.args.profile self.name = name self._playlist = None self._scene = app.scene self._main_buffer = None self._secondary_buffer = None self._in_transition = False self._transition = None self.transition_progress = 0.0 self._start_transition = False self._transition_list = [] self._transition_duration = self._app.settings.get( 'mixer')['transition-duration'] self._transition_slop = self._app.settings.get( 'mixer')['transition-slop'] self._elapsed = 0 self._duration = self._app.settings.get('mixer')['preset-duration'] # Load transitions self.set_transition_mode(self._app.settings.get('mixer')['transition']) if not self._scene: pass else: self._main_buffer = BufferUtils.create_buffer() self._secondary_buffer = BufferUtils.create_buffer()
def get(self, start, end, progress): start[self.mask] = 0.0 end[np.invert(self.mask)] = 0.0 idx = int(progress * len(self.rand_index)) if idx >= self.last_idx: for i in range(self.last_idx, idx): fix = self.fixtures[self.rand_index[i]] self._strobing.append(fix) self._time[fix] = progress self._on[fix] = True else: for i in range(idx, self.last_idx): fix = self.fixtures[self.rand_index[i]] if fix in self._strobing: self._strobing.remove(fix) pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end][:] = False self._on[fix] = False self.last_idx = idx for fix in self._strobing: pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end][:] = self._on[fix] self._on[fix] = not self._on[fix] if progress > self._time[fix] + self._duration: self._strobing.remove(fix) self.mask[pix_start:pix_end][:] = True return (start) + (end)
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
def __init__(self, app): super(Mixer, self).__init__() self._app = app self._net = app.net self._playlist = None self._scene = app.scene self._tick_rate = self._app.settings.get('mixer')['tick-rate'] self._in_transition = False self._start_transition = False self._transition_duration = self._app.settings.get('mixer')['transition-duration'] self._transition_slop = self._app.settings.get('mixer')['transition-slop'] self._tick_timer = None self._duration = self._app.settings.get('mixer')['preset-duration'] self._elapsed = 0.0 self._running = False self._enable_rendering = True self._main_buffer = None self._max_fixtures = 0 self._max_pixels = 0 self._tick_time_data = dict() self._num_frames = 0 self._last_frame_time = 0.0 self._start_time = 0.0 self._stop_time = 0.0 self._strand_keys = list() self._enable_profiling = self._app.args.profile self._paused = self._app.settings.get('mixer').get('paused', False) self._frozen = False self._random_transition = False self._last_onset_time = 0.0 self._onset_holdoff = self._app.settings.get('mixer')['onset-holdoff'] self._onset = False self._reset_onset = False self._global_dimmer = 1.0 self._global_speed = 1.0 self._render_in_progress = False # Load transitions self.set_transition_mode(self._app.settings.get('mixer')['transition']) if not self._scene: log.warn("No scene assigned to mixer. Preset rendering and transitions are disabled.") self._transition_duration = 0.0 self._enable_rendering = False else: log.info("Initializing preset rendering buffer") fh = self._scene.fixture_hierarchy() for strand in fh: self._strand_keys.append(strand) (maxs, maxf, maxp) = self._scene.get_matrix_extents() self._main_buffer = BufferUtils.create_buffer(self._app) self._secondary_buffer = BufferUtils.create_buffer(self._app) self._max_fixtures = maxf self._max_pixels = maxp log.info("Warming up BufferUtils cache...") BufferUtils.warmup(self._app) log.info("Completed BufferUtils cache warmup")
def setup(self): self.add_parameter(StringParameter('first-preset', "")) self.add_parameter(StringParameter('second-preset', "")) self.add_parameter(FloatParameter('transition-progress', 0.5)) self.add_parameter(FloatParameter('audio-transition', 0.0)) self.add_parameter(StringParameter('transition-mode', "Additive Blend")) self._preset1_buffer = BufferUtils.create_buffer() self._preset2_buffer = BufferUtils.create_buffer()
def __init__(self, app): super(Mixer, self).__init__() self._app = app self._net = app.net self._playlist = None self._scene = app.scene self._tick_rate = self._app.settings.get('mixer')['tick-rate'] self._in_transition = False self._start_transition = False self._transition_duration = self._app.settings.get('mixer')['transition-duration'] self._transition_slop = self._app.settings.get('mixer')['transition-slop'] self._tick_timer = None self._duration = self._app.settings.get('mixer')['preset-duration'] self._elapsed = 0.0 self._running = False self._enable_rendering = True self._main_buffer = None self._max_fixtures = 0 self._max_pixels = 0 self._tick_time_data = dict() self._num_frames = 0 self._last_frame_time = 0.0 self._start_time = 0.0 self._stop_time = 0.0 self._strand_keys = list() self._enable_profiling = self._app.args.profile self._paused = False self._frozen = False self._random_transition = False self._last_onset_time = 0.0 self._onset_holdoff = self._app.settings.get('mixer')['onset-holdoff'] self._onset = False self._reset_onset = False self._global_dimmer = 1.0 # Load transitions self.set_transition_mode(self._app.settings.get('mixer')['transition']) if not self._scene: log.warn("No scene assigned to mixer. Preset rendering and transitions are disabled.") self._transition_duration = 0.0 self._enable_rendering = False else: log.info("Initializing preset rendering buffer") fh = self._scene.fixture_hierarchy() for strand in fh: self._strand_keys.append(strand) (maxs, maxf, maxp) = self._scene.get_matrix_extents() self._main_buffer = BufferUtils.create_buffer(self._app) self._secondary_buffer = BufferUtils.create_buffer(self._app) self._max_fixtures = maxf self._max_pixels = maxp log.info("Warming up BufferUtils cache...") BufferUtils.warmup(self._app) log.info("Completed BufferUtils cache warmup")
def setup(self): self.x, self.y = BufferUtils.get_buffer_size(self._app) self.pixel_locations = self._app.scene.get_all_pixel_locations() self.pixel_addr = {} for pixel, _ in self.pixel_locations: self.pixel_addr[pixel] = BufferUtils.get_buffer_address(self._app, pixel) self.reset()
def setup(self): self.add_parameter(StringParameter('first-preset', "")) self.add_parameter(StringParameter('second-preset', "")) self.add_parameter(FloatParameter('transition-progress', 0.5)) self.add_parameter(StringParameter('transition-mode', "Additive Blend")) self.add_parameter(StringParameter('layer', 'default')) self.parameter_changed(None) self._preset1_buffer = BufferUtils.create_buffer() self._preset2_buffer = BufferUtils.create_buffer()
def setup(self): self.x, self.y = BufferUtils.get_buffer_size(self._app) self.pixel_locations = self._app.scene.get_all_pixel_locations() self.pixel_addr = {} for pixel, _ in self.pixel_locations: self.pixel_addr[pixel] = BufferUtils.get_buffer_address( self._app, pixel) self.reset()
def get_pixel_location(self, index): """ Returns a given pixel's location in scene coordinates. """ loc = self._pixel_locations_cache.get(index, None) if loc is None: strand, address, pixel = BufferUtils.index_to_logical(index) f = self.fixture(strand, address) if pixel == 0: loc = f.pos1 elif pixel == (f.pixels - 1): loc = f.pos2 else: x1, y1 = f.pos1 x2, y2 = f.pos2 scale = old_div(float(pixel), f.pixels) relx, rely = ((x2 - x1) * scale, (y2 - y1) * scale) loc = (x1 + relx, y1 + rely) self._pixel_locations_cache[index] = loc return loc
def tick(self): self._num_frames += 1 if len(self._playlist) > 0: self._playlist.get_active_preset().clear_commands() self._playlist.get_active_preset().tick() transition_progress = 0.0 # Handle transition by rendering both the active and the next preset, and blending them together if self._in_transition: if self._start_transition: self._start_transition = False if self._random_transition: self.get_next_transition() if self._transition: self._transition.reset() self._playlist.get_next_preset()._reset() self._secondary_buffer = BufferUtils.create_buffer(self._app) if self._transition_duration > 0.0 and self._transition is not None: transition_progress = self._elapsed / self._transition_duration else: transition_progress = 1.0 self._playlist.get_next_preset().clear_commands() self._playlist.get_next_preset().tick() # Exit from transition state after the transition duration has elapsed if transition_progress >= 1.0: self._in_transition = False # Reset the elapsed time counter so the preset runs for the full duration after the transition self._elapsed = 0.0 self._playlist.advance() # If the scene tree is available, we can do efficient mixing of presets. # If not, a tree would need to be constructed on-the-fly. # TODO: Support mixing without a scene tree available if self._enable_rendering: if self._in_transition: self.render_presets(self._playlist.get_active_index(), self._playlist.get_next_index(), transition_progress) else: self.render_presets(self._playlist.get_active_index()) else: if self._net is not None: self._net.write(self._playlist.get_active_preset().get_commands_packed()) if not self._paused and (self._elapsed >= self._duration) and self._playlist.get_active_preset().can_transition() and not self._in_transition: if (self._elapsed >= (self._duration + self._transition_slop)) or self._onset: if len(self._playlist) > 1: self.start_transition() self._elapsed = 0.0 if self._reset_onset: self._onset = False self._reset_onset = False if self._enable_profiling: tick_time = (time.time() - self._last_frame_time) self._last_frame_time = time.time() if tick_time > 0.0: index = int((1.0 / tick_time)) self._tick_time_data[index] = self._tick_time_data.get(index, 0) + 1
def get_fixture_bounding_box(self): """ Returns the bounding box containing all fixtures in the scene Return value is a tuple of (xmin, ymin, xmax, ymax) """ xmin = 999999 xmax = -999999 ymin = 999999 ymax = -999999 fh = self.fixture_hierarchy() for strand in fh: for fixture in fh[strand]: for pixel in range(self.fixture(strand, fixture).pixels): x, y = self.get_pixel_location( BufferUtils.logical_to_index((strand, fixture, pixel))) if x < xmin: xmin = x if x > xmax: xmax = x if y < ymin: ymin = y if y > ymax: ymax = y return (xmin, ymin, xmax, ymax)
def init_pixels(self): """ Sets up the pixel array """ (self._max_strand, self._max_fixture, self._max_pixel) = self.scene().get_matrix_extents() self._pixel_buffer = BufferUtils.create_buffer()
def warmup(self): """ Warms up caches """ log.info("Warming up scene caches...") fh = self.fixture_hierarchy() for strand in fh: for fixture in fh[strand]: self.get_colliding_fixtures(strand, fixture) for pixel in range(self.fixture(strand, fixture).pixels): index = BufferUtils.logical_to_index( (strand, fixture, pixel)) neighbors = self.get_pixel_neighbors(index) self.get_pixel_location(index) for neighbor in neighbors: self.get_pixel_distance(index, neighbor) self.get_fixture_bounding_box() self.get_intersection_points() self.get_all_pixels_logical() self._tree = spatial.KDTree(self.get_all_pixel_locations()) locations = self.get_all_pixel_locations() self.pixelDistances = np.empty([len(locations), len(locations)]) for pixel in range(len(locations)): cx, cy = locations[pixel] x, y = (locations - (cx, cy)).T pixel_distances = np.sqrt(np.square(x) + np.square(y)) self.pixelDistances[pixel] = pixel_distances log.info("Done")
def reset(self): self.buffer_size = BufferUtils.get_buffer_size() self.scene_bb = self._app.scene.get_fixture_bounding_box() self.scene_center = (self.scene_bb[0] + (self.scene_bb[2] - self.scene_bb[0]) / 2, self.scene_bb[1] + (self.scene_bb[3] - self.scene_bb[1]) / 2) dx = self.scene_bb[2] - self.scene_center[0] dy = self.scene_bb[3] - self.scene_center[1] self.scene_radius = sqrt(pow(dx, 2) + pow(dy, 2)) self.locations = self._app.scene.get_all_pixel_locations() self.angles = {} self.radii = {} for pixel, location in enumerate(self.locations): dy = location[1] - self.scene_center[1] dx = location[0] - self.scene_center[0] angle = (atan2(dy, dx) + pi) / (2.0 * pi) self.radii[pixel] = sqrt(pow(dx, 2) + pow(dy, 2)) self.angles[pixel] = angle self.mask = np.tile(False, (self.buffer_size, 3)) self.angle = 0.0 self.radius = 0.0 self.active = [ True, ] * len(self.locations)
def warmup(self): """ Warms up caches """ log.info("Warming up scene caches...") fh = self.fixture_hierarchy() for strand in fh: for fixture in fh[strand]: self.get_colliding_fixtures(strand, fixture) for pixel in range(self.fixture(strand, fixture).pixels): index = BufferUtils.logical_to_index((strand, fixture, pixel)) neighbors = self.get_pixel_neighbors(index) self.get_pixel_location(index) for neighbor in neighbors: self.get_pixel_distance(index, neighbor) self.get_fixture_bounding_box() self.get_intersection_points() self.get_all_pixels_logical() self._tree = spatial.KDTree(self.get_all_pixel_locations()) locations = self.get_all_pixel_locations() self.pixelDistances = np.empty([len(locations), len(locations)]) for pixel in range(len(locations)): cx, cy = locations[pixel] x,y = (locations - (cx, cy)).T pixel_distances = np.sqrt(np.square(x) + np.square(y)) self.pixelDistances[pixel] = pixel_distances log.info("Done")
def get_pixel_location(self, index): """ Returns a given pixel's location in scene coordinates. """ loc = self._pixel_locations_cache.get(index, None) if loc is None: strand, address, pixel = BufferUtils.index_to_logical(index) f = self.fixture(strand, address) if pixel == 0: loc = f.pos1 elif pixel == (f.pixels - 1): loc = f.pos2 else: x1, y1 = f.pos1 x2, y2 = f.pos2 scale = float(pixel) / f.pixels relx, rely = ((x2 - x1) * scale, (y2 - y1) * scale) loc = (x1 + relx, y1 + rely) self._pixel_locations_cache[index] = loc return loc
def get_fixture_bounding_box(self): """ Returns the bounding box containing all fixtures in the scene Return value is a tuple of (xmin, ymin, xmax, ymax) """ xmin = 999999 xmax = -999999 ymin = 999999 ymax = -999999 fh = self.fixture_hierarchy() for strand in fh: for fixture in fh[strand]: for pixel in range(self.fixture(strand, fixture).pixels): x, y = self.get_pixel_location(BufferUtils.logical_to_index((strand, fixture, pixel))) if x < xmin: xmin = x if x > xmax: xmax = x if y < ymin: ymin = y if y > ymax: ymax = y return (xmin, ymin, xmax, ymax)
def __init__(self, app): super(Mixer, self).__init__() self._app = app self._net = app.net self._scene = app.scene self._tick_rate = self._app.settings.get('mixer')['tick-rate'] self._tick_timer = None self._running = False self._enable_rendering = True self._main_buffer = None self._tick_time_data = dict() self._num_frames = 0 self._last_frame_time = 0.0 self._start_time = 0.0 self._stop_time = 0.0 self._enable_profiling = self._app.args.profile self._paused = self._app.settings.get('mixer').get('paused', False) self._frozen = False self._last_onset_time = 0.0 self._onset_holdoff = self._app.settings.get('mixer')['onset-holdoff'] self._onset = False self._reset_onset = False self._global_dimmer = 1.0 self._global_speed = 1.0 self._render_in_progress = False self._last_tick_time = time.time() self._audio_emitters_by_group = {} self._layers = [] if self._app.args.yappi and USE_YAPPI: yappi.start() if not self._scene: log.warn( "No scene assigned to mixer. Preset rendering and transitions are disabled." ) self._enable_rendering = False else: log.info("Warming up BufferUtils cache...") BufferUtils.init() log.info("Completed BufferUtils cache warmup") log.info("Initializing preset rendering buffer") fh = self._scene.fixture_hierarchy() self._main_buffer = BufferUtils.create_buffer()
def setup(self): self.num_strands, self.num_pixels = BufferUtils.get_buffer_size(self._app) self.scene_bb = self._app.scene.get_fixture_bounding_box() self.scene_center = (self.scene_bb[0] + (self.scene_bb[2] - self.scene_bb[0]) / 2, self.scene_bb[1] + (self.scene_bb[3] - self.scene_bb[1]) / 2) dx = self.scene_bb[2] - self.scene_center[0] dy = self.scene_bb[3] - self.scene_center[1] self.radius = math.sqrt(math.pow(dx,2) + math.pow(dy, 2))
def __init__(self, app): super(Mixer, self).__init__() self._app = app self._net = app.net self._scene = app.scene self._tick_rate = self._app.settings.get('mixer')['tick-rate'] self._tick_timer = None self._running = False self._enable_rendering = True self._main_buffer = None self._tick_time_data = dict() self._num_frames = 0 self._last_frame_time = 0.0 self._start_time = 0.0 self._stop_time = 0.0 self._enable_profiling = self._app.args.profile self._paused = self._app.settings.get('mixer').get('paused', False) self._frozen = False self._last_onset_time = 0.0 self._onset_holdoff = self._app.settings.get('mixer')['onset-holdoff'] self._onset = False self._reset_onset = False self._global_dimmer = 1.0 self._global_speed = 1.0 self._render_in_progress = False self._last_tick_time = time.time() self._audio_emitters_by_group = {} self._layers = [] self._leap_controller = Leap.Controller() if self._app.args.yappi and USE_YAPPI: yappi.start() if not self._scene: log.warn("No scene assigned to mixer. Preset rendering and transitions are disabled.") self._enable_rendering = False else: log.info("Warming up BufferUtils cache...") BufferUtils.init() log.info("Completed BufferUtils cache warmup") log.info("Initializing preset rendering buffer") fh = self._scene.fixture_hierarchy() self._main_buffer = BufferUtils.create_buffer()
def setup(self): self.num_strands, self.num_pixels = BufferUtils.get_buffer_size(self._app) bb = self._app.scene.get_fixture_bounding_box() self.scene_center = np.asarray([bb[0] + (bb[2] - bb[0]) / 2, bb[1] + (bb[3] - bb[1]) / 2]) self.bb = bb self.reset()
def __init__(self, args, parent=None): self._running = False self.args = args self.settings = Settings() self.net = Networking(self) BufferUtils.set_app(self) self.scene = Scene(self) self.plugins = PluginLoader() self.mixer = Mixer(self) # Create the default layer. default_playlist = Playlist(self, self.args.playlist, 'last_playlist') default_layer = Layer(self, 'default') default_layer.set_playlist(default_playlist) self.mixer.add_layer(default_layer) if self.args.speech_layer: speech_playlist = Playlist(self, self.args.speech_playlist, 'last_speech_playlist') speech_layer = Layer(self, 'speech') speech_layer.set_playlist(speech_playlist) self.mixer.add_layer(speech_layer) if self.args.route_layer: route_playlist = Playlist(self, self.args.route_playlist, 'last_route_playlist') route_layer = Layer(self, 'routes') route_layer.set_playlist(route_playlist) self.mixer.add_layer(route_layer) self.scene.warmup() self.aubio_connector = None if not self.args.noaudio: self.aubio_connector = AubioConnector() self.aubio_connector.onset_detected.connect(self.mixer.onset_detected) self.osc_server = None if not self.args.noosc: self.osc_server = OscServer( self.args.osc_port, self.args.mixxx_osc_port, self.mixer) self.osc_server.start() if self.args.preset: log.info("Setting constant preset %s" % args.preset) self.mixer.set_constant_preset(args.preset) QtCore.QThread.__init__(self, parent)
def reset(self): x, y = BufferUtils.get_buffer_size(self._app) self.mask = np.tile(False, (x, y, 3)) np.random.seed() self.rand_index = np.arange(len(self.fixtures)) np.random.shuffle(self.rand_index) self.last_idx = 0
def reset(self): self.buffer_size = BufferUtils.get_buffer_size() self.mask = np.tile(False, self.buffer_size) np.random.seed() self.rand_index = np.arange(self.buffer_size) np.random.shuffle(self.rand_index) self.last_idx = 0
def reset(self): self.buffer_size = BufferUtils.get_buffer_size() self.mask = np.tile(False, (self.buffer_size, 3)) num_elements = np.ndarray.flatten(self.mask).size / 3 np.random.seed() self.rand_index = np.arange(num_elements) np.random.shuffle(self.rand_index) self.last_idx = 0
def reset(self): self.fixtures = self._app.scene.fixtures() buffer_size = BufferUtils.get_buffer_size() self.mask = np.tile(False, (buffer_size, 3)) np.random.seed() self.rand_index = np.arange(len(self.fixtures)) np.random.shuffle(self.rand_index) self.last_idx = 0
def reset(self): x, y = BufferUtils.get_buffer_size(self._app) self.mask = np.tile(False, (x, y, 3)) num_elements = np.ndarray.flatten(self.mask).size np.random.seed() self.rand_index = np.arange(num_elements) np.random.shuffle(self.rand_index) self.last_idx = 0
def __init__(self, args, parent=None): self._running = False self.args = args self.settings = Settings() self.net = Networking(self) BufferUtils.set_app(self) self.scene = Scene(self) self.plugins = PluginLoader() self.mixer = Mixer(self) # Create the default layer. default_playlist = Playlist(self, self.args.playlist, 'last_playlist') default_layer = Layer(self, 'default') default_layer.set_playlist(default_playlist) self.mixer.add_layer(default_layer) if self.args.speech_layer: speech_playlist = Playlist(self, self.args.speech_playlist, 'last_speech_playlist') speech_layer = Layer(self, 'speech') speech_layer.set_playlist(speech_playlist) self.mixer.add_layer(speech_layer) self.scene.warmup() self.aubio_connector = None if not self.args.noaudio: self.aubio_connector = AubioConnector() self.aubio_connector.onset_detected.connect( self.mixer.onset_detected) self.osc_server = None if not self.args.noosc: self.osc_server = OscServer(self.args.osc_port, self.args.mixxx_osc_port, self.mixer) self.osc_server.start() if self.args.preset: log.info("Setting constant preset %s" % args.preset) self.mixer.set_constant_preset(args.preset) QtCore.QThread.__init__(self, parent)
def setup(self): self.num_strands, self.num_pixels = BufferUtils.get_buffer_size(self._app) self.scene_bb = self._app.scene.get_fixture_bounding_box() self.scene_center = (self.scene_bb[0] + (self.scene_bb[2] - self.scene_bb[0]) / 2, self.scene_bb[1] + (self.scene_bb[3] - self.scene_bb[1]) / 2) dx = self.scene_bb[2] - self.scene_center[0] dy = self.scene_bb[3] - self.scene_center[1] self.scene_radius = sqrt(pow(dx,2) + pow(dy, 2)) self.locations = self._app.scene.get_all_pixel_locations() self.buffer_addr = {} self.angles = {} self.radii = {} for pixel, location in self.locations: self.buffer_addr[pixel] = BufferUtils.get_buffer_address(self._app, pixel) dy = location[1] - self.scene_center[1] dx = location[0] - self.scene_center[0] angle = (atan2(dy, dx) + pi) / (2.0 * pi) self.radii[pixel] = sqrt(pow(dx,2) + pow(dy, 2)) self.angles[pixel] = angle
def render(self, start, end, progress, out): start[self.mask] = (0.0, 0.0, 0.0) end[np.invert(self.mask)] = (0.0, 0.0, 0.0) idx = int(progress * len(self.rand_index)) if idx >= self.last_idx: for i in range(self.last_idx, idx): fix = self.fixtures[self.rand_index[i]] pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end] = True else: for i in range(idx, self.last_idx): fix = self.fixtures[self.rand_index[i]] pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end]= False self.last_idx = idx np.add(struct_flat(start), struct_flat(end), struct_flat(out))
def __init__(self, parent, args): QtCore.QThread.__init__(self, parent) self._running = False self.args = args self.settings = Settings() self.net = Networking(self) BufferUtils.set_app(self) self.scene = Scene(self) self.plugins = PluginLoader() self.mixer = Mixer(self) self.playlist = Playlist(self) self.qt_app = parent self.gui = None self.scene.warmup() self.mixer.set_playlist(self.playlist) if self.args.preset: log.info("Setting constant preset %s" % args.preset) self.mixer.set_constant_preset(args.preset)
def get(self, start, end, progress): for strand, address, pixel, location in self.locations: dy = math.fabs(location[1] - self.scene_center[1]) dx = math.fabs(location[0] - self.scene_center[0]) if math.sqrt(math.pow(dx,2) + math.pow(dy, 2)) < (self.radius * progress): _, pixel = BufferUtils.get_buffer_address(self._app, (strand, address, pixel)) self.mask[strand][pixel][:] = True start[self.mask] = 0.0 end[np.invert(self.mask)] = 0.0 return start + end
def get(self, start, end, progress): start[self.mask] = 0.0 end[np.invert(self.mask)] = 0.0 idx = int(progress * len(self.rand_index)) for i in range(self.last_idx, idx): fix = self.fixtures[self.rand_index[i]] pix_start, pix_end = BufferUtils.get_fixture_extents(fix.strand, fix.address) self.mask[pix_start:pix_end][:] = True self.last_idx = idx return (start) + (end)
def setup(self): self.num_strands, self.num_pixels = BufferUtils.get_buffer_size( self._app) self.scene_bb = self._app.scene.get_fixture_bounding_box() self.scene_center = (self.scene_bb[0] + (self.scene_bb[2] - self.scene_bb[0]) / 2, self.scene_bb[1] + (self.scene_bb[3] - self.scene_bb[1]) / 2) dx = self.scene_bb[2] - self.scene_center[0] dy = self.scene_bb[3] - self.scene_center[1] self.radius = math.sqrt(math.pow(dx, 2) + math.pow(dy, 2))
def get(self, start, end, progress): start[self.mask] = 0.0 end[np.invert(self.mask)] = 0.0 idx = int(progress * len(self.rand_index)) for i in range(self.last_idx, idx): fix = self.fixtures[self.rand_index[i]] pix_start, pix_end = BufferUtils.get_fixture_extents( fix.strand, fix.address) self.mask[pix_start:pix_end][:] = True self.last_idx = idx return (start) + (end)
def get_all_pixels(self): """ Returns a list of all pixels in buffer address format (strand, offset) """ if self._all_pixels_raw is None: all_pixels = [] for s, a, p in self.get_all_pixels_logical(): #pxs.append(BufferUtils.get_buffer_address((s, a, p), scene=self)) all_pixels.append(BufferUtils.logical_to_index((s, a, p), scene=self)) all_pixels = sorted(all_pixels) self._all_pixels_raw = all_pixels return self._all_pixels_raw
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
def render(self, out): # Spontaneous birth: Rare after startup if (len(self._dragons) < self.parameter('pop-limit').get() ) and random.random() < self.parameter('birth-rate').get(): strand = random.randint(0, BufferUtils.num_strands - 1) fixture = random.randint( 0, BufferUtils.strand_num_fixtures(strand) - 1) address = BufferUtils.logical_to_index((strand, fixture, 0)) if address not in [d.loc for d in self._dragons]: self._dragons.add(_Dragon(self, address, 1, self._current_time)) # Dragon life cycle to_add = set() to_remove = set() population = len(self._dragons) for dragon in self._dragons: population += dragon.render(to_add, to_remove, population) self._dragons = (self._dragons | to_add) - to_remove # Draw tails tails_to_remove = [] for loc, time, fader in self._tails: if (self._current_time - time) > self.parameter('tail-persist').get(): if (loc, time, fader) in self._tails: tails_to_remove.append((loc, time, fader)) self.setPixelHLS(self._buffer, loc, (0, 0, 0)) else: progress = (self._current_time - time) / self.parameter('tail-persist').get() self.setPixelHLS(self._buffer, loc, fader.get_color(progress * self._fader_steps)) for tail in tails_to_remove: self._tails.remove(tail) np.copyto(out, self._buffer)
def get_all_pixels(self): """ Returns a list of all pixels in buffer address format (strand, offset) """ if self._all_pixels_raw is None: all_pixels = [] for s, a, p in self.get_all_pixels_logical(): #pxs.append(BufferUtils.get_buffer_address((s, a, p), scene=self)) all_pixels.append( BufferUtils.logical_to_index((s, a, p), scene=self)) all_pixels = sorted(all_pixels) self._all_pixels_raw = all_pixels return self._all_pixels_raw
def get(self, start, end, progress): """ Simple wipe """ # Move the wipe point along the wipe line wipe_point = self.wipe_start + (progress * self.wipe_line_vector) # Mask based on the wipe point for strand, address, pixel, location in self.locations: if np.dot(location - wipe_point, self.wipe_vector) < 0: _, pixel = BufferUtils.get_buffer_address(self._app, (strand, address, pixel)) self.mask[strand][pixel][:] = True start[self.mask] = 0.0 end[np.invert(self.mask)] = 0.0 return start + end