Пример #1
0
 def test_add_second_piece(self):
     gatherer = Gatherer()
     gatherer.add(Piece(10, 20))
     gatherer.add(Piece(40, 50))
     expected_pieces = [Piece(10, 20),
                        Piece(40, 50)]
     self.assertEquals(expected_pieces, gatherer.pieces())
Пример #2
0
 def test_fit_hole(self):
     gatherer = Gatherer()
     gatherer.add(Piece(10, 20))
     gatherer.add(Piece(40, 50))
     gatherer.add(Piece(20, 40))
     expected_pieces = [Piece(10, 50)]
     self.assertEquals(expected_pieces, gatherer.pieces())
Пример #3
0
 def test_overlap_multiple_pieces(self):
     gatherer = Gatherer()
     gatherer.add(Piece(10, 20))
     gatherer.add(Piece(30, 40))
     gatherer.add(Piece(0, 50))
     expected_pieces = [Piece(0, 50)]
     self.assertEquals(expected_pieces, gatherer.pieces())
Пример #4
0
 def test_prepend(self):
     gatherer = Gatherer()
     gatherer.add(Piece(10, 20))
     gatherer.add(Piece(40, 50))
     gatherer.add(Piece(30, 40))
     expected_pieces = [Piece(10, 20),
                        Piece(30, 50)]
     self.assertEquals(expected_pieces, gatherer.pieces())
Пример #5
0
 def test_multiple_files_append(self):
     f1 = File(offset=0, length=30)
     f2 = File(offset=30, length=20)
     gatherer = Gatherer()
     gatherer.add(Piece(20, 30, f1))
     gatherer.add(Piece(0, 10, f2))
     expected_pieces = [Piece(20, 40, f1)]
     self.assertEquals(expected_pieces, gatherer.pieces())
Пример #6
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.gatherer = Gatherer()
        self.x_scope = DynamicScope()

    def add_segment(self, segment):
        self.x_scope.put(segment.begin)
        self.x_scope.put(segment.end)
        segment.pan = (self.x_scope.map(segment.begin) + self.x_scope.map(segment.end)) / 2
        segment.departure_position = segment.peer_position()
        self.visualizer.playing_segment(segment, segment.pan)

    def render(self):
        self.x_scope.update()
        self.draw_gathered_segments()

    def draw_gathered_segments(self):
        for segment in self.gatherer.pieces():
            segment.draw_gathered()

    def byte_to_step_position(self, byte):
        return float(byte) / self.length * NUM_STEPS

    def byte_to_wall_position(self, byte):
        step_position = self.byte_to_step_position(byte)
        step = int(step_position)+1
        return Vector2d(self.visualizer.step_z(step_position),
                        self.visualizer.step_y(step))

    def byte_surfaces(self, begin, end, min_size=None):
        step_pos1 = self.byte_to_step_position(begin)
        step_pos2 = self.byte_to_step_position(end)
        if (step_pos2 - step_pos1) < min_size:
            step_pos1, step_pos2 = self.resize(step_pos1, step_pos2, min_size)
        step1 = int(step_pos1)
        step2 = int(step_pos2)
        fraction1 = step_pos1 % 1
        fraction2 = step_pos2 % 1
        for step in range(step1, step2+1):
            if step == step1:
                relative_begin = fraction1
            else:
                relative_begin = 0

            if step == step2:
                relative_end = fraction2
            else:
                relative_end = 1

            step_surfaces = list(self.visualizer.step_surfaces(step, relative_begin, relative_end))
            yield step_surfaces[1]

    def resize(self, pos1, pos2, new_size):
        new_pos1 = max(pos1 - new_size/2, 0)
        new_pos2 = min(pos2 + new_size/2, NUM_STEPS)
        return new_pos1, new_pos2
Пример #7
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.gatherer = Gatherer()
        self.x_scope = DynamicScope()

    def add_segment(self, segment):
        self.x_scope.put(segment.begin)
        self.x_scope.put(segment.end)
        segment.pan = (self.x_scope.map(segment.begin) + self.x_scope.map(segment.end)) / 2
        segment.departure_position = segment.peer_position()
        self.visualizer.playing_segment(segment)

    def render(self):
        self.x_scope.update()
        self.draw_gathered_segments()

    def draw_gathered_segments(self):
        for segment in self.gatherer.pieces():
            segment.draw_gathered()

    def byte_to_coord(self, byte):
        return self.visualizer.prepend_margin_width + \
            self.x_scope.map(byte) * self.visualizer.safe_width
Пример #8
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.gatherer = Gatherer()
        self.y = self.visualizer.step_y(self.filenum+1)
        self.z1 = self.visualizer.step_z(self.filenum)
        self.z2 = self.visualizer.step_z(self.filenum+1)
        self.z = (self.z1 + self.z2) / 2
        self.neighbour_y = self.visualizer.step_y(self.filenum+2)
        self.neighbour_z1 = self.visualizer.step_z(self.filenum+1)

    def add_segment(self, segment):
        segment.departure_position = segment.peer.position
        self.visualizer.playing_segment(segment)

    def render(self):
        self.draw_gathered_segments()

    def draw_gathered_segments(self):
        for segment in self.gatherer.pieces():
            segment.draw_gathered()

    def byte_to_x(self, byte):
        return WALL_X + float(byte) / self.length * STAIRS_WIDTH
Пример #9
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.playing_chunks = OrderedDict()
        self.gatherer = Gatherer()

    def add_chunk(self, chunk):
        self.playing_chunks[chunk.id] = chunk

    def update(self):
        outdated = filter(lambda chunk_id: self.playing_chunks[chunk_id].age() > DURATION,
                          self.playing_chunks)
        for chunk_id in outdated:
            self.gatherer.add(self.playing_chunks[chunk_id])
            del self.playing_chunks[chunk_id]

    def render(self):
        self.y = float(self.visualizer.height) / (self.visualizer.num_files + 1) * (
            self.filenum + 1)
        self.y1 = int(self.y - GATHERED_HEIGHT/2)
        self.y2 = int(self.y + GATHERED_HEIGHT/2)

        self.draw_background()
        self.draw_gathered_chunks()
        self.draw_playing_chunks()

    def draw_background(self):
        x1 = self.byte_to_px(0)
        x2 = self.byte_to_px(self.length)
        self.visualizer.set_color(BACKGROUND_COLOR)
        glBegin(GL_QUADS)
        glVertex2i(x1, self.y2)
        glVertex2i(x2, self.y2)
        glVertex2i(x2, self.y1)
        glVertex2i(x1, self.y1)
        glEnd()

    def draw_gathered_chunks(self):
        for chunk in self.gatherer.pieces():
            self.draw_gathered_chunk(chunk)

    def draw_playing_chunks(self):
        for chunk in self.playing_chunks.values():
            self.draw_playing_chunk(chunk)

    def draw_gathered_chunk(self, chunk):
        self.visualizer.set_color(GATHERED_COLOR)
        x1, x2 = self.chunk_position(chunk)
        glBegin(GL_QUADS)
        glVertex2i(x1, self.y2)
        glVertex2i(x2, self.y2)
        glVertex2i(x2, self.y1)
        glVertex2i(x1, self.y1)
        glEnd()

    def draw_playing_chunk(self, chunk):
        height = PLAYING_HEIGHT
        y1 = int(self.y - height/2)
        y2 = int(self.y + height/2)
        self.visualizer.set_color(PLAYING_COLOR)
        x1 = self.byte_to_px(chunk.begin)
        x2 = self.byte_to_px(chunk.end)
        x2 = max(x2, x1 + 1)
        glBegin(GL_QUADS)
        glVertex2i(x1, y2)
        glVertex2i(x2, y2)
        glVertex2i(x2, y1)
        glVertex2i(x1, y1)
        glEnd()

    def chunk_position(self, chunk):
        x1 = self.byte_to_px(chunk.begin)
        x2 = self.byte_to_px(chunk.end)
        x2 = max(x2, x1 + 1)
        return x1, x2

    def byte_to_px(self, byte):
        return MARGIN + int(
            float((self.visualizer.max_file_length - self.length) / 2 + byte) / \
            self.visualizer.max_file_length * (self.visualizer.width - 2*MARGIN))
Пример #10
0
class Waves(visualizer.Visualizer):
    def __init__(self, args):
        visualizer.Visualizer.__init__(self, args,
                                       file_class=File,
                                       segment_class=Segment)
        self.subscribe_to_waveform()

    def reset(self):
        visualizer.Visualizer.reset(self)
        self.playing_segments = collections.OrderedDict()
        self.gatherer = Gatherer()

    def pan_segment(self, segment):
        # let orchestra & synth spatialize
        pass

    def InitGL(self):
        visualizer.Visualizer.InitGL(self)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        self._gathered_segments_layer = self.new_layer(self._render_gathered_segments)

    def update(self):
        outdated = []
        for segment in self.playing_segments.values():
            if not segment.is_playing():
                self.gatherer.add(segment)
                outdated.append(segment.id)

        if len(outdated) > 0:
            for segment_id in outdated:
                del self.playing_segments[segment_id]
            self._gathered_segments_layer.refresh()

    def render(self):
        self.update()
        self._gathered_segments_layer.draw()
        self.draw_playing_segments()

    def draw_playing_segments(self):
        glEnable(GL_LINE_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        for segment in self.playing_segments.values():
            segment.render()

    def _render_gathered_segments(self):
        glBegin(GL_QUADS)
        x1 = 0
        x2 = self.width
        min_height = GATHERED_LINE_WIDTH * self.height
        for segment in self.gatherer.pieces():
            y1 = self.byte_to_py(segment.torrent_begin)
            y2 = max(self.byte_to_py(segment.torrent_end), y1 + min_height)
            if (y2 - y1) > min_height:
                d = min((y2 - y1) * 0.2, MAX_GRADIENT_HEIGHT * self.height)
                y1d = y1 + d
                y2d = y2 - d

                glColor3f(0, 0, 0)
                glVertex2f(x1, y1)

                glColor3f(*GATHERED_COLOR)
                glVertex2f(x1, y1d)
                glVertex2f(x2, y1d)

                glColor3f(0, 0, 0)
                glVertex2f(x2, y1)



                glColor3f(0, 0, 0)
                glVertex2f(x1, y2)

                glColor3f(*GATHERED_COLOR)
                glVertex2f(x1, y2d)
                glVertex2f(x2, y2d)

                glColor3f(0, 0, 0)
                glVertex2f(x2, y2)


                glColor3f(*GATHERED_COLOR)
                glVertex2f(x1, y1d)
                glVertex2f(x1, y2d)
                glVertex2f(x2, y2d)
                glVertex2f(x2, y1d)
            else:
                glColor3f(0, 0, 0)
                glVertex2f(x1, y1)

                glColor3f(*GATHERED_COLOR)
                glVertex2f(x1, y2)
                glVertex2f(x2, y2)

                glColor3f(0, 0, 0)
                glVertex2f(x2, y1)
        glEnd()

    def byte_to_py(self, byte):
        return int(self.byte_to_relative_y(byte) * self.height)

    def byte_to_relative_y(self, byte):
        return float(byte) / self.torrent_length

    def handle_segment_waveform_value(self, segment, value):
        segment.waveform.appendleft(value)

    def finished(self):
        if len(self.gatherer.pieces()) == 1:
            piece = self.gatherer.pieces()[0]
            return piece.begin == 0 and piece.end == self.torrent_length
        else:
            return False
Пример #11
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.playing_segments = OrderedDict()
        self.gatherer = Gatherer()
        self.x_scope = DynamicScope()

    def add_segment(self, segment):
        self.x_scope.put(segment.begin)
        self.x_scope.put(segment.end)
        pan = (self.byte_to_coord(segment.begin) + self.byte_to_coord(segment.end)) / 2
        self.visualizer.playing_segment(segment, pan)
        self.playing_segments[segment.id] = segment

    def update(self):
        outdated = filter(lambda segment_id: self.playing_segments[segment_id].relative_age() > 1,
                          self.playing_segments)
        for segment_id in outdated:
            self.gatherer.add(self.playing_segments[segment_id])
            del self.playing_segments[segment_id]
        self.x_scope.update()

    def render(self):
        self.y = self.visualizer.filenum_to_y_coord(self.filenum)
        self.draw_gathered_segments()
        self.draw_playing_segments()

    def draw_gathered_segments(self):
        for segment in self.gatherer.pieces():
            self.draw_segment(segment, 0)

    def draw_playing_segments(self):
        for segment in self.playing_segments.values():
            self.draw_playing_segment(segment)

    def draw_playing_segment(self, segment):
        actuality = 1 - segment.relative_age()
        self.draw_segment(segment, actuality)

    def draw_segment(self, segment, actuality):
        y_offset = actuality * 10
        height = 3 + actuality * 10
        y1 = int(self.y + y_offset)
        y2 = int(self.y + y_offset + height)
        x1 = self.visualizer.prepend_margin_width + \
            int(self.byte_to_coord(segment.begin) * self.visualizer.safe_width)
        x2 = self.visualizer.prepend_margin_width + \
            int(self.byte_to_coord(segment.end) * self.visualizer.safe_width)
        x1, x2 = self.upscale(x1, x2, actuality)
        if x2 == x1:
            x2 = x1 + 1
        opacity = 0.2 + (actuality * 0.8)
        glColor3f(1-opacity, 1-opacity, 1-opacity)
        glBegin(GL_LINE_LOOP)
        glVertex2i(x1, y2)
        glVertex2i(x2, y2)
        glVertex2i(x2, y1)
        glVertex2i(x1, y1)
        glEnd()

    def upscale(self, x1, x2, actuality):
        unscaled_size = x2 - x1
        desired_size = actuality * ARRIVAL_SIZE
        if desired_size > unscaled_size:
            mid = (x1 + x2) / 2
            half_desired_size = int(desired_size/2)
            x1 = mid - half_desired_size
            x2 = mid + half_desired_size
        return (x1, x2)

    def byte_to_coord(self, byte):
        return self.x_scope.map(byte)
Пример #12
0
 def test_overlap_begin(self):
     gatherer = Gatherer()
     gatherer.add(Piece(10, 20))
     gatherer.add(Piece(0, 15))
     expected_pieces = [Piece(0, 20)]
     self.assertEquals(expected_pieces, gatherer.pieces())
Пример #13
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.position = self.visualizer.position_for_new_file()
        self.gatherer = Gatherer()
        self.inner_radius = self.visualizer.scale(RADIUS - CIRCLE_THICKNESS)
        self.radius = self.visualizer.scale(RADIUS)
        self.velocity = Vector2d(0,0)

    def add_segment(self, segment):
        #I suppose this is non-SSR panning?
        #pan = self.completion_position(segment.begin, self.radius).x / self.visualizer.width
        self.visualizer.playing_segment(segment)
        segment.departure_position = segment.peer_position()

    def draw(self):
        glLineWidth(1)
        opacity = 0.5
        glColor3f(1-opacity, 1-opacity, 1-opacity)

        if self.completed():
            self.draw_completed_file()
        else:
            for segment in self.gatherer.pieces():
                self.draw_gathered_piece(segment)

    def completed(self):
        if len(self.gatherer.pieces()) == 1:
            piece = self.gatherer.pieces()[0]
            return piece.byte_size == self.length

    def draw_gathered_piece(self, segment):
        num_vertices = int(CIRCLE_PRECISION * float(segment.end - segment.begin) / segment.byte_size)
        num_vertices = max(num_vertices, 2)
        glBegin(GL_LINE_LOOP)

        for i in range(num_vertices):
            byte_position = segment.begin + segment.byte_size * float(i) / (num_vertices-1)
            p = self.completion_position(byte_position, self.inner_radius)
            glVertex2f(p.x, p.y)
        for i in range(num_vertices):
            byte_position = segment.begin + segment.byte_size * float(num_vertices-i-1) / (num_vertices-1)
            p = self.completion_position(byte_position, self.radius)
            glVertex2f(p.x, p.y)

        glEnd()

    def draw_completed_file(self):
        num_vertices = int(CIRCLE_PRECISION)

        glBegin(GL_LINE_LOOP)
        for i in range(num_vertices):
            byte_position = self.length * float(i) / (num_vertices-1)
            p = self.completion_position(byte_position, self.inner_radius)
            glVertex2f(p.x, p.y)
        glEnd()

        glBegin(GL_LINE_LOOP)
        for i in range(num_vertices):
            byte_position = self.length * float(i) / (num_vertices-1)
            p = self.completion_position(byte_position, self.radius)
            glVertex2f(p.x, p.y)
        glEnd()

    def completion_position(self, byte_cursor, radius):
        angle = self.byte_cursor_to_angle(byte_cursor)
        return self.completion_position_by_angle(angle, radius)

    def completion_position_by_angle(self, angle, radius):
        x = self.visualizer.x_offset + self.position.x + radius * math.cos(angle)
        y = self.visualizer.y_offset + self.position.y + radius * math.sin(angle)
        return Vector2d(x, y)

    def byte_cursor_to_angle(self, byte_cursor):
        return 2 * math.pi * float(byte_cursor) / self.length
Пример #14
0
class Stairs(visualizer.Visualizer):
    def __init__(self, args):
        visualizer.Visualizer.__init__(self, args,
                                       file_class=File,
                                       peer_class=Peer,
                                       segment_class=Segment)
        self.inner_x = WALL_X
        self.outer_x = WALL_X + STAIRS_WIDTH
        self.wall_rear_x = WALL_X - WALL_WIDTH
        self.wall_bottom = self.step_y(NUM_STEPS) - STEP_HEIGHT
        self.stairs_depth = self.step_z(NUM_STEPS)
        self.files = {}
        self.segments = {}
        self.gatherer = Gatherer()
        self._segments_split_at_step_boundaries = None
        self._dragging_orientation = False
        self._dragging_y_position = False
        self._set_camera_position(CAMERA_POSITION)
        self._set_camera_orientation(CAMERA_Y_ORIENTATION, CAMERA_X_ORIENTATION)
        self.enable_accum()
        self.enable_3d()
        if self.args.waveform:
            self.gathered_color_v = CURSOR_COLOR_V * GATHERED_OPACITY + STEPS_COLOR_V * (1 - GATHERED_OPACITY)
            self.gathered_color_h = CURSOR_COLOR_H * GATHERED_OPACITY + STEPS_COLOR_H * (1 - GATHERED_OPACITY)
            self.subscribe_to_waveform()
        else:
            self.gathered_color_v = GATHERED_COLOR_V
            self.gathered_color_h = GATHERED_COLOR_H
            self.subscribe_to_amp()

    def gather(self, segment):
        self.gatherer.add(segment)
        self._segments_split_at_step_boundaries = None

    def added_all_files(self):
        self._create_steps()

    def _create_steps(self):
        self._steps = []
        remaining_bytes = self.torrent_length
        remaining_num_steps = NUM_STEPS
        byte_offset = 0
        for n in range(NUM_STEPS):
            byte_size = int(remaining_bytes / remaining_num_steps)
            self._steps.append(Step(self, n, byte_offset, byte_size))
            byte_offset += byte_size
            remaining_bytes -= byte_size
            remaining_num_steps -= 1

    def pan_segment(self, segment):
        x = WALL_X + STAIRS_WIDTH/2
        self.place_segment(segment.id,
                           segment.step.z, x,
                           segment.duration)

    def render(self):
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_POLYGON_OFFSET_FILL)
        for peer in self.peers.values():
            peer.update()
        self.accum(self.render_accum_objects)
        if len(self.files) > 0:
            self.draw_branches()

        glDisable(GL_DEPTH_TEST)
        self.draw_step_edges()
        self.draw_wall_edge()

    def render_accum_objects(self):
        glPolygonOffset(1.0, 0.0)
        self.draw_step_surfaces()
        self.draw_wall_surfaces()
        if len(self.files) > 0:
            glPolygonOffset(0.0, 0.0)
            self.draw_gathered_segments()

    def draw_branches(self):
        for peer in self.peers.values():
            peer.draw()

    def draw_step_surfaces(self):
        self.draw_step_horizontal_surfaces()
        self.draw_step_vertical_surfaces()

    def draw_step_horizontal_surfaces(self):
        glColor3f(*STEPS_COLOR_H)
        glBegin(GL_QUADS)
        for n in range(0, NUM_STEPS):
            surface = self.step_h_surface(n)
            for vertex in surface:
                glVertex3f(*vertex)
        glEnd()

    def draw_step_vertical_surfaces(self):
        glColor3f(*STEPS_COLOR_V)
        glBegin(GL_QUADS)
        for n in range(1, NUM_STEPS+1):
            surface = self.step_v_surface(n)
            for vertex in surface:
                glVertex3f(*vertex)
        glEnd()

    def draw_step_edges(self):
        glLineWidth(1.0)
        glColor3f(*STEPS_COLOR_V)
        for n in range(1, NUM_STEPS+1):
            y = self.step_y(n)
            z = self.step_z(n)
            glBegin(GL_LINES)
            glVertex3f(self.inner_x, y, z)
            glVertex3f(self.outer_x, y, z)
            glEnd()

    def draw_wall_edge(self):
        glLineWidth(1.0)
        glColor3f(*WALL_SHADE_COLOR_H)
        glBegin(GL_LINES)
        glVertex3f(self.inner_x, WALL_TOP, self.stairs_depth)
        glVertex3f(self.inner_x, self.wall_bottom, self.stairs_depth)
        glEnd()

    def draw_wall_surfaces(self):
        glColor3f(*WALL_SHADE_COLOR_H)
        glBegin(GL_QUADS)
        glVertex3f(self.inner_x, WALL_TOP, 0)
        glVertex3f(self.inner_x, WALL_TOP, self.stairs_depth)
        glVertex3f(self.wall_rear_x, WALL_TOP, self.stairs_depth)
        glVertex3f(self.wall_rear_x, WALL_TOP, 0)
        glEnd()

        glColor3f(*WALL_SHADE_COLOR_V)
        glBegin(GL_QUADS)
        glVertex3f(self.inner_x, WALL_TOP, self.stairs_depth)
        glVertex3f(self.wall_rear_x, WALL_TOP, self.stairs_depth)
        glVertex3f(self.wall_rear_x, self.wall_bottom, self.stairs_depth)
        glVertex3f(self.inner_x, self.wall_bottom, self.stairs_depth)
        glEnd()

        glColor3f(*WALL_COLOR)
        glBegin(GL_QUADS)
        glVertex3f(self.inner_x, WALL_TOP, 0)
        glVertex3f(self.inner_x, WALL_TOP, self.stairs_depth)
        glVertex3f(self.inner_x, self.wall_bottom, self.stairs_depth)
        glVertex3f(self.inner_x, self.wall_bottom, 0)
        glEnd()

        for n in range(1, NUM_STEPS+1):
            glBegin(GL_POLYGON)
            z = self.step_z(n)
            y1 = self.step_y(n)
            y2 = self.step_y(n+1)
            glVertex3f(self.outer_x, y1, z)
            glVertex3f(self.outer_x, y2, z)
            glVertex3f(self.outer_x, y2, 0)
            glVertex3f(self.outer_x, y1, 0)
            glEnd()
        

    def step_h_surface(self, n):
        y1 = self.step_y(n)
        y2 = self.step_y(n+1)
        
        z1 = self.step_z(n)
        z2 = self.step_z(n+1)

        return [
            Vector3d(self.inner_x, y2, z1),
            Vector3d(self.inner_x, y2, z2),
            Vector3d(self.outer_x, y2, z2),
            Vector3d(self.outer_x, y2, z1)
            ]

    def step_v_surface(self, n):
        y1 = self.step_y(n)
        y2 = self.step_y(n+1)
        
        z1 = self.step_z(n)
        z2 = self.step_z(n+1)

        return [
            Vector3d(self.inner_x, y1, z1),
            Vector3d(self.inner_x, y2, z1),
            Vector3d(self.outer_x, y2, z1),
            Vector3d(self.outer_x, y1, z1)
            ]

    def step_y(self, step):
        return -step * STEP_HEIGHT

    def step_z(self, step):
        return step * STEP_DEPTH

    def draw_gathered_segments(self):
        if self._segments_split_at_step_boundaries is None:
            self._segments_split_at_step_boundaries = self._split_segments_at_step_boundaries(
                self.gatherer.pieces())
        for segment in self._segments_split_at_step_boundaries:
            segment.draw_gathered()

    def _split_segments_at_step_boundaries(self, pieces):
        result = []
        for piece in pieces:
            segments = self._split_at_step_boundaries(piece)
            result.extend(segments)
        return result

    def _split_at_step_boundaries(self, segment):
        result = []
        for step in self._steps:
            if self._segment_matches_step(segment, step):
                new_segment = copy.copy(segment)
                new_segment.torrent_begin = max(segment.torrent_begin, step.byte_offset)
                new_segment.torrent_end = min(segment.torrent_end, step.byte_offset + step.byte_size)
                new_segment.step = step
                result.append(new_segment)
        return result

    def _segment_matches_step(self, segment, step):
        return (step.byte_offset <= segment.torrent_begin < (step.byte_offset + step.byte_size) or
                step.byte_offset < segment.torrent_end <= (step.byte_offset + step.byte_size))

    def _byte_to_step(self, byte):
        for step in self._steps:
            if step.byte_offset <= byte and byte < step.byte_end:
                return step
        raise Exception("failed to get step for byte %s with steps %s" % (byte, self._steps))

    def handle_segment_waveform_value(self, segment, value):
        segment.waveform.appendleft(value)

    def handle_segment_amplitude(self, segment, amp):
        segment.amp = amp
Пример #15
0
class File(visualizer.File):
    def __init__(self, *args):
        visualizer.File.__init__(self, *args)
        self.playing_segments = OrderedDict()
        self.gatherer = Gatherer()

    def add_segment(self, segment):
        segment.pan = self.byte_to_relative_x((segment.begin + segment.end) / 2)
        self.visualizer.playing_segment(segment)
        self.playing_segments[segment.id] = segment

    def update(self):
        outdated = filter(lambda segment_id: self.playing_segments[segment_id].relative_age() > 1,
                          self.playing_segments)
        for segment_id in outdated:
            self.gatherer.add(self.playing_segments[segment_id])
            del self.playing_segments[segment_id]

    def render(self):
        self.y = float(self.visualizer.height) / (self.visualizer.num_files + 1) * (
            self.filenum + 1)
        self.y1 = int(self.y - GATHERED_HEIGHT/2)
        self.y2 = int(self.y + GATHERED_HEIGHT/2)

        self.draw_background()
        self.draw_gathered_segments()
        self.draw_playing_segments()

    def draw_background(self):
        x1 = self.byte_to_px(0)
        x2 = self.byte_to_px(self.length)
        self.visualizer.set_color(BACKGROUND_COLOR)
        glBegin(GL_QUADS)
        glVertex2i(x1, self.y2)
        glVertex2i(x2, self.y2)
        glVertex2i(x2, self.y1)
        glVertex2i(x1, self.y1)
        glEnd()

    def draw_gathered_segments(self):
        for segment in self.gatherer.pieces():
            self.draw_gathered_segment(segment)

    def draw_playing_segments(self):
        for segment in self.playing_segments.values():
            self.draw_playing_segment(segment)

    def draw_gathered_segment(self, segment):
        self.visualizer.set_color(GATHERED_COLOR)
        x1, x2 = self.segment_position(segment)
        glBegin(GL_QUADS)
        glVertex2i(x1, self.y2)
        glVertex2i(x2, self.y2)
        glVertex2i(x2, self.y1)
        glVertex2i(x1, self.y1)
        glEnd()

    def draw_playing_segment(self, segment):
        trace_age = 0.1
        previous_byte_cursor = segment.begin + max(segment.age()-trace_age, 0) / \
                segment.duration * segment.byte_size
        height = PLAYING_HEIGHT
        y1 = int(self.y - height/2)
        y2 = int(self.y + height/2)
        x0 = self.byte_to_px(segment.begin)
        x1 = self.byte_to_px(previous_byte_cursor)
        x3 = self.byte_to_px(segment.playback_byte_cursor())
        x3 = max(x3, x1 + 1)
        x2 = (x1 + x3) / 2

        self.visualizer.set_color(GATHERED_COLOR)
        glBegin(GL_QUADS)
        glVertex2i(x0, y1)
        glVertex2i(x0, y2)
        glVertex2i(x1, y2)
        glVertex2i(x1, y1)
        glEnd()

        glBegin(GL_QUADS)
        self.visualizer.set_color(GATHERED_COLOR)
        glVertex2i(x1, y2)
        glVertex2i(x1, y1)
        self.visualizer.set_color(PLAYING_COLOR)
        glVertex2i(x2, y1)
        glVertex2i(x2, y2)
        glEnd()

        glBegin(GL_QUADS)
        self.visualizer.set_color(PLAYING_COLOR)
        glVertex2i(x2, y1)
        glVertex2i(x2, y2)
        self.visualizer.set_color(GATHERED_COLOR)
        glVertex2i(x3, y2)
        glVertex2i(x3, y1)
        glEnd()

    def segment_position(self, segment):
        x1 = self.byte_to_px(segment.begin)
        x2 = self.byte_to_px(segment.end)
        x2 = max(x2, x1 + 1)
        return x1, x2

    def byte_to_px(self, byte):
        return MARGIN + int(self.byte_to_relative_x(byte) * (self.visualizer.width - 2*MARGIN))

    def byte_to_relative_x(self, byte):
        return float((self.visualizer.max_file_length - self.length) / 2 + byte) / \
            self.visualizer.max_file_length
Пример #16
0
class File:
    def __init__(self, length, visualizer):
        self.visualizer = visualizer
        self.arriving_chunks = OrderedDict()
        self.gatherer = Gatherer()
        
    def add_chunk(self, chunk):
        chunk.boid = Boid(self.get_departure_position(chunk), 10.0, 3.0)
        chunk.target = None
        chunk.target_type = None
        chunk.target_position = None
        chunk.target_position = self.get_target_position(chunk)
        chunk.boid.arrive(chunk.target_position)
        chunk.arrived = False
        self.arriving_chunks[chunk.id] = chunk

    def stopped_playing(self, chunk_id):
        chunk = self.arriving_chunks[chunk_id]
        self.gather_chunk(chunk)

    def gather_chunk(self, chunk):
        del self.arriving_chunks[chunk.id]
        # TODO: verify that these positions are really OK
        chunk.begin_position = Vector(chunk.boid.loc.x, chunk.boid.loc.y)
        chunk.end_position = Vector(chunk.boid.loc.x, chunk.boid.loc.y)
        self.gatherer.add(chunk)
        self.reorient_chunks_following(chunk)

    def get_departure_position(self, chunk):
        if chunk.pan < 0.5:
            x = 0
        else:
            x = self.visualizer.width
        y = chunk.height * self.visualizer.height
        return Vector(x, y)

    def get_target_position(self, chunk):
        if not chunk.target_position:
            self.find_target(chunk)
        return chunk.target_position

    def find_target(self, chunk):
        position = self.find_joinable_piece(chunk)
        if position:
            chunk.target_type = TargetType.PIECE
            chunk.target_position = position
            return

        other_chunk = self.find_other_huntable_chunk(chunk)
        if other_chunk:
            chunk.target_type = TargetType.CHUNK
            chunk.target = other_chunk
            chunk.target_position = other_chunk.boid.loc
            return

        if len(self.gatherer.pieces()) > 0:
            chunk.target_position = self.close_to_existing_piece()
            return

        chunk.target_type = TargetType.NEW_PIECE
        chunk.target_position = self.anywhere()

    def anywhere(self):
        return Vector(random.uniform(self.visualizer.width * INNER_MARGIN,
                                     self.visualizer.width * (1 - INNER_MARGIN*2)),
                      random.uniform(self.visualizer.height * INNER_MARGIN,
                                     self.visualizer.height * (1 - INNER_MARGIN*2)))

    def close_to_existing_piece(self):
        piece = random.choice(self.gatherer.pieces())
        position = random.choice([piece.begin_position,
                                  piece.end_position])
        angle = random.uniform(0, 2 * math.pi)
        distance = 1.0
        movement = Vector(distance * math.cos(angle),
                          distance * math.sin(angle))
        return position + movement

    def find_joinable_piece(self, chunk):
        appendable_piece_key = self.gatherer.find_appendable_piece(chunk)
        prependable_piece_key = self.gatherer.find_prependable_piece(chunk)
        if appendable_piece_key and prependable_piece_key:
            appendable_position = self.gatherer.piece(appendable_piece_key).begin_position
            prepandable_position = self.gatherer.piece(prependable_piece_key).end_position
            chunk.target_position = (appendable_position + prepandable_position) / 2
        elif appendable_piece_key:
            return self.gatherer.piece(appendable_piece_key).begin_position
        elif prependable_piece_key:
            return self.gatherer.piece(prependable_piece_key).end_position
    
    def find_other_huntable_chunk(self, chunk):
        # optimization: iterate appendables in reverse order, or use some kind of cache
        for other in self.arriving_chunks.values():
            if other.end == chunk.begin:
                return other
            if other.begin == chunk.end:
                return other

    def reorient_chunks_following(self, targeted_chunk):
        for chunk in self.arriving_chunks.values():
            if chunk.target_type == TargetType.CHUNK and \
                    chunk.target == targeted_chunk:
                self.find_target(chunk)

    def update(self):
        self.update_pieces()
        self.update_arriving_chunks()

    def update_pieces(self):
        for piece in self.gatherer.pieces():
            self.get_piece_force(piece)
        for piece in self.gatherer.pieces():
            self.apply_piece_force(piece)

    def get_piece_force(self, piece):
        piece.desired_length = self.desired_piece_length(piece)
        piece.begin_force = Vector(0,0)
        piece.end_force = Vector(0,0)
        self.consider_desired_length(piece, piece.begin_force, piece.begin_position, piece.end_position)
        self.consider_desired_length(piece, piece.end_force, piece.end_position, piece.begin_position)
        piece.begin_force.limit(3.0)
        piece.end_force.limit(3.0)

    def desired_piece_length(self, piece):
        return piece.byte_size / 10

    def consider_desired_length(self, piece, force, position, opposite_position):
        force += spring_force(position, opposite_position, piece.desired_length)

    def apply_piece_force(self, piece):
        piece.begin_position += piece.begin_force
        piece.end_position += piece.end_force

    def update_arriving_chunks(self):
        for chunk in self.arriving_chunks.values():
            if not chunk.arrived:
                chunk.boid.update()
                if self.arrived(chunk):
                    #self.visualizer.play_chunk(chunk) # TEMP
                    chunk.arrived = True
                    self.gather_chunk(chunk) # TEMP

    def arrived(self, chunk):
        if chunk.target_type in [TargetType.PIECE,
                                 TargetType.NEW_PIECE]:
            distance = (chunk.target_position - chunk.boid.loc).mag()
            return distance < 1.0
        else:
            return False
Пример #17
0
class Waves(visualizer.Visualizer):
    def __init__(self, args):
        self._gathered_segments_layer = None
        visualizer.Visualizer.__init__(self, args,
                                       file_class=File,
                                       peer_class=Peer,
                                       segment_class=Segment)
        if self.args.peer_info:
            self.layout_managers = {"left":  LayoutManager1d(),
                                    "right": LayoutManager1d()}
        self.waves_margin = self.parse_margin_argument(self.args.waves_margin)
        
    @staticmethod
    def add_parser_arguments(parser):
        visualizer.Visualizer.add_parser_arguments(parser)
        parser.add_argument("--peer-info", action="store_true")
        parser.add_argument("--enable-title", action="store_true")
        parser.add_argument("--title-size", type=float, default=30.0)
        parser.add_argument("--test-title", type=str)
        visualizer.Visualizer.add_margin_argument(parser, "--waves-margin")

    def resized_window(self):
        self.waves_margin.update()
        self._waves_width = self.width - self.waves_margin.left - self.waves_margin.right
        self._waves_right = self.width - self.waves_margin.right
        self._waves_height = self.height - self.waves_margin.top - self.waves_margin.bottom
        self._waves_top = self.height - self.waves_margin.top
        self._title_renderer = None

    def configure_2d_projection(self):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0.0, self.window_width, 0.0, self.window_height, -1.0, 1.0)
        glMatrixMode(GL_MODELVIEW)

    def synth_address_received(self):
        self.subscribe_to_waveform()

    def reset(self):
        visualizer.Visualizer.reset(self)
        self.playing_segments = collections.OrderedDict()
        self.gatherer = Gatherer()
        if self._gathered_segments_layer:
            self._gathered_segments_layer.refresh()
        self._first_segment_received = False
        self._title_renderer = None

    def pan_segment(self, segment):
        # let orchestra & synth spatialize
        pass

    def InitGL(self):
        visualizer.Visualizer.InitGL(self)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        self._gathered_segments_layer = self.new_layer(self._render_gathered_segments)

    def update(self):
        outdated = []
        for segment in self.playing_segments.values():
            if not segment.is_playing():
                self.gatherer.add(segment)
                outdated.append(segment.id)

        if len(outdated) > 0:
            for segment_id in outdated:
                self.playing_segments[segment_id].free()
                del self.playing_segments[segment_id]
            self._gathered_segments_layer.refresh()

    def render(self):
        self._set_gathered_color()
        self._gathered_segments_layer.draw()
        self.draw_playing_segments()

        if self.args.enable_title:
            if not self._title_renderer and (self._first_segment_received or self.args.test_title):
                self._create_title_renderer()
            if self._title_renderer:
                self._render_title()

    def _create_title_renderer(self):
        if self.args.test_title:
            title = self.args.test_title
        else:
            title = self.torrent_title
        size = self.args.title_size / 1024 * self.width
        self._title_renderer = TitleRenderer(title, size, self)

    def _render_title(self):
        if self.download_completed():
            color = self._fade_out_color()
        else:
            color = Vector3d(1,1,1)
        glColor3f(*color)
        x = self.waves_margin.left + 10.0 / 640 * self.width
        y = self.height * 0.03
        self._title_renderer.render(x, y)

    def _set_gathered_color(self):
        if self.download_completed():
            self.gathered_color = self._fade_out_color()
            self._gathered_segments_layer.refresh()
        elif self.torrent_length > 0:
            torrent_progress = float(self.gatherer.gathered_bytes()) / self.torrent_length
            self.gathered_color = GATHERED_COLOR + (WAVEFORM_COLOR - GATHERED_COLOR) * pow(torrent_progress, 20)
        else:
            self.gathered_color = GATHERED_COLOR

    def _fade_out_color(self):
        time_after_completion = max(self.now - self.torrent_download_completion_time, 0)
        if time_after_completion > FADE_OUT_DURATION:
            return Vector3d(0,0,0)
        else:
            return WAVEFORM_COLOR * pow(1 - time_after_completion/FADE_OUT_DURATION, 0.15)

    def active(self):
        return len(self.playing_segments) > 0

    def finished(self):
        if self.download_completed():
            time_after_completion = max(self.now - self.torrent_download_completion_time, 0)
            if time_after_completion > FADE_OUT_DURATION:
                return True

    def draw_playing_segments(self):
        glEnable(GL_LINE_SMOOTH)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        for segment in self.playing_segments.values():
            segment.render()

    def _render_gathered_segments(self):
        glBegin(GL_QUADS)
        x1 = self.waves_margin.left
        x2 = self._waves_right
        min_height = GATHERED_LINE_WIDTH * self._waves_height
        for segment in self.gatherer.pieces():
            y1 = self.byte_to_py(segment.torrent_begin)
            y2 = max(self.byte_to_py(segment.torrent_end), y1 + min_height)
            if (y2 - y1) > min_height:
                d = min((y2 - y1) * 0.2, MAX_GRADIENT_HEIGHT * self._waves_height)
                y1d = y1 + d
                y2d = y2 - d

                glColor3f(0, 0, 0)
                glVertex2f(x1, y1)

                glColor3f(*self.gathered_color)
                glVertex2f(x1, y1d)
                glVertex2f(x2, y1d)

                glColor3f(0, 0, 0)
                glVertex2f(x2, y1)



                glColor3f(0, 0, 0)
                glVertex2f(x1, y2)

                glColor3f(*self.gathered_color)
                glVertex2f(x1, y2d)
                glVertex2f(x2, y2d)

                glColor3f(0, 0, 0)
                glVertex2f(x2, y2)


                glColor3f(*self.gathered_color)
                glVertex2f(x1, y1d)
                glVertex2f(x1, y2d)
                glVertex2f(x2, y2d)
                glVertex2f(x2, y1d)
            else:
                glColor3f(0, 0, 0)
                glVertex2f(x1, y1)

                glColor3f(*self.gathered_color)
                glVertex2f(x1, y2)
                glVertex2f(x2, y2)

                glColor3f(0, 0, 0)
                glVertex2f(x2, y1)
        glEnd()

    def byte_to_py(self, byte):
        return int(self.waves_margin.bottom + self.byte_to_relative_y(byte) * self._waves_height)

    def byte_to_relative_y(self, byte):
        return float(byte) / self.torrent_length

    def handle_segment_waveform_value(self, segment, value):
        segment.append_to_waveform(value)
Пример #18
0
class Waves(visualizer.Visualizer):
    def __init__(self, args):
        visualizer.Visualizer.__init__(self, args,
                                       file_class=File,
                                       peer_class=Peer,
                                       segment_class=Segment)
        self.subscribe_to_waveform()
        self.playing_segments = collections.OrderedDict()
        self.gatherer = Gatherer()

    def gather(self, segment):
        self.gatherer.add(segment)

    def render(self):
        #self.draw_outline()
        self.draw_gathered_segments()
        for peer in self.peers.values():
            peer.update()
            peer.draw()

    def draw_outline(self):
        glDisable(GL_LINE_SMOOTH)
        glLineWidth(1.0)
        glColor3f(*OUTLINE_COLOR)
        glBegin(GL_LINE_STRIP)
        glVertex2f(self.x1, self.y1)
        glVertex2f(self.x1, self.y2)
        glVertex2f(self.x2, self.y2)
        glVertex2f(self.x2, self.y1)
        glVertex2f(self.x1, self.y1)
        glEnd()

    def draw_gathered_segments(self):
        glColor3f(*GATHERED_COLOR)
        glBegin(GL_QUADS)
        for segment in self.gatherer.pieces():
            y1 = self.byte_to_py(segment.torrent_begin)
            y2 = self.byte_to_py(segment.torrent_end)
            if y2 == y1:
                y2 += 1
            glVertex2f(self.x1, y1)
            glVertex2f(self.x1, y2)
            glVertex2f(self.x2, y2)
            glVertex2f(self.x2, y1)
        glEnd()

    def byte_to_py(self, byte):
        return self.y1 + int(self.byte_to_relative_y(byte) * (self.y2 - self.y1))

    def byte_to_relative_y(self, byte):
        return float(byte) / self.torrent_length

    def handle_segment_waveform_value(self, segment, value):
        segment.add_to_waveform(value)

    def ReSizeGLScene(self, *args):
        visualizer.Visualizer.ReSizeGLScene(self, *args)
        margin_x = FILE_MARGIN_X * self.width
        margin_y = FILE_MARGIN_Y * self.height
        self.x1 = margin_x
        self.y1 = margin_y
        self.x2 = self.width - margin_x
        self.y2 = self.height - margin_y
        self.waveform_length_to_file = margin_x
        self.waveform_length_in_file = self.x2 - self.x1