예제 #1
0
파일: layer.py 프로젝트: shakaran/pitivi
    def __init__(self, ges_layer, timeline):
        Gtk.EventBox.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.ges_layer = ges_layer
        self.ges_layer.ui = self
        self.timeline = timeline
        self.app = timeline.app

        self.ges_layer.connect("clip-added", self._clipAddedCb)
        self.ges_layer.connect("clip-removed", self._clipRemovedCb)

        # FIXME Make the layer height user setable with 'Paned'
        self.props.height_request = ui.LAYER_HEIGHT / 2
        self.props.valign = Gtk.Align.START

        self._layout = LayerLayout(self.timeline)
        self._layout.connect("remove", self.__childWidgetRemovedCb)
        self.add(self._layout)

        self.media_types = GES.TrackType(0)
        for clip in ges_layer.get_clips():
            self._addClip(clip)

        self.before_sep = SpacedSeparator(Gtk.PositionType.TOP)
        self.after_sep = SpacedSeparator(Gtk.PositionType.BOTTOM)
예제 #2
0
    def __init__(self, ges_elem):
        Previewer.__init__(self, GES.TrackType.AUDIO)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.pipeline = None
        self._wavebin = None

        self.discovered = False
        self.ges_elem = ges_elem
        self.timeline = ges_elem.get_parent().get_timeline().ui

        asset = self.ges_elem.get_parent().get_asset()
        self.n_samples = asset.get_duration() / SAMPLE_DURATION
        self.samples = None
        self.peaks = None
        self._start = 0
        self._end = 0
        self._surface_x = 0

        # Guard against malformed URIs
        self.wavefile = None
        self._uri = quote_uri(get_proxy_target(ges_elem).props.id)

        self._num_failures = 0
        self.adapter = None
        self.surface = None

        self._force_redraw = True

        self.ges_elem.connect("notify::in-point", self._inpointChangedCb)
예제 #3
0
    def test_marker_moved_ui(self):
        """Checks the move marker UI."""
        markers = self.timeline.get_marker_list("markers")
        marker_box = self.timeline_container.markers

        x1 = 300
        position1 = Zoomable.pixel_to_ns(x1)
        marker = marker_box.markers_container.add(position1)
        self.assert_markers(markers, [(position1, None)])

        x2 = 400
        position2 = Zoomable.pixel_to_ns(x2)

        event = mock.Mock(spec=Gdk.EventButton)
        event.x = x2
        event.y = 1
        event.type = Gdk.EventType.BUTTON_PRESS
        event.button = Gdk.BUTTON_PRIMARY

        with mock.patch.object(Gtk, "get_event_widget") as get_event_widget:
            get_event_widget.return_value = marker.ui
            event.guiEvent = Gdk.Event.new(Gdk.EventType.BUTTON_PRESS)
            marker_box.do_button_press_event(event)

            with mock.patch.object(
                    marker.ui,
                    "translate_coordinates") as translate_coordinates:
                translate_coordinates.return_value = (x2, 0)
                marker_box.do_motion_notify_event(event)
                marker_box.do_button_release_event(event)

        self.assert_markers(markers, [(position2, None)])
예제 #4
0
    def __init__(self, app, hadj=None):
        Gtk.EventBox.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.layout = Gtk.Layout()
        self.add(self.layout)
        self.get_style_context().add_class("MarkersBox")

        self.app = app

        if hadj:
            hadj.connect("value-changed", self._hadj_value_changed_cb)
        self.props.hexpand = True
        self.props.valign = Gtk.Align.START

        self.offset = 0
        self.props.height_request = MARKER_WIDTH

        self.__markers_container = None
        self.marker_moving = None
        self.marker_new = None

        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK |
                        Gdk.EventMask.BUTTON_PRESS_MASK |
                        Gdk.EventMask.BUTTON_RELEASE_MASK)

        self._create_actions()
예제 #5
0
파일: ruler.py 프로젝트: elaa0505/pitivi
    def __init__(self, timeline):
        Gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")

        self.timeline = timeline
        self._pipeline = None
        hadj = timeline.timeline.hadj
        hadj.connect("value-changed", self._hadj_value_changed_cb)
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK
                        | Gdk.EventMask.BUTTON_PRESS_MASK
                        | Gdk.EventMask.BUTTON_RELEASE_MASK
                        | Gdk.EventMask.SCROLL_MASK)

        self.pixbuf = None

        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0

        self.position = 0  # In nanoseconds
        self.frame_rate = Gst.Fraction(1 / 1)
        self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND

        self.scales = SCALES
예제 #6
0
파일: elements.py 프로젝트: jojva/pitivi
    def __init__(self, bElement, track, timeline):
        """
        @param bElement : the backend GES.TrackElement
        @param track : the track to which the bElement belongs
        @param timeline : the containing graphic timeline.
        """
        Zoomable.__init__(self)
        Clutter.Actor.__init__(self)

        self.timeline = timeline
        self.bElement = bElement
        self.bElement.selected = Selected()
        self.track_type = self.bElement.get_track_type()  # This won't change
        self.isDragged = False
        size = self.bElement.get_duration()

        self._createBackground(track)
        self._createPreview()
        self._createBorder()
        self._createMarquee()
        self._createHandles()
        self._createGhostclip()

        self.update(True)
        self.set_reactive(True)

        self._connectToEvents()
예제 #7
0
    def __init__(self, ges_elem, max_cpu_usage):
        Previewer.__init__(self, GES.TrackType.AUDIO, max_cpu_usage)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.pipeline = None
        self._wavebin = None

        self.discovered = False
        self.ges_elem = ges_elem
        self.timeline = ges_elem.get_parent().get_timeline().ui

        asset = self.ges_elem.get_parent().get_asset()
        self.n_samples = asset.get_duration() / SAMPLE_DURATION
        self.samples = None
        self.peaks = None
        self._start = 0
        self._end = 0
        self._surface_x = 0

        # Guard against malformed URIs
        self.wavefile = None
        self._uri = quote_uri(get_proxy_target(ges_elem).props.id)

        self._num_failures = 0
        self.adapter = None
        self.surface = None

        self._force_redraw = True

        self.ges_elem.connect("notify::in-point", self._inpoint_changed_cb)
        self.connect("notify::height-request", self._height_changed_cb)
        self.becomeControlled()
예제 #8
0
    def __init__(self, gui, instance, ui_manager):
        Zoomable.__init__(self)
        Gtk.VBox.__init__(self)

        GObject.threads_init()

        self.gui = gui
        self.ui_manager = ui_manager
        self.app = instance
        self._settings = None
        if self.app:
            self._settings = self.app.settings

        self._projectmanager = None
        self._project = None
        self.pipeline = None

        self._createUi()
        self._createActions()

        self._setUpDragAndDrop()

        if self._settings:
            self._settings.connect("edgeSnapDeadbandChanged",
                                   self._snapDistanceChangedCb)

        # Standalone
        if not self._settings:
            gtksettings = Gtk.Settings.get_default()
            gtksettings.set_property("gtk-application-prefer-dark-theme", True)

        self.show_all()
예제 #9
0
파일: layer.py 프로젝트: dz0ny/pitivi
    def __init__(self, ges_layer, timeline):
        Gtk.EventBox.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.ges_layer = ges_layer
        self.ges_layer.ui = self
        self.timeline = timeline
        self.app = timeline.app

        self.ges_layer.connect("clip-added", self._clipAddedCb)
        self.ges_layer.connect("clip-removed", self._clipRemovedCb)

        # FIXME Make the layer height user setable with 'Paned'
        self.props.height_request = ui.LAYER_HEIGHT / 2
        self.props.valign = Gtk.Align.START

        self._layout = LayerLayout(self.timeline)
        self._layout.connect("remove", self.__childWidgetRemovedCb)
        self.add(self._layout)

        self.media_types = GES.TrackType(0)
        for clip in ges_layer.get_clips():
            self._addClip(clip)

        self.before_sep = SpacedSeparator(Gtk.PositionType.TOP)
        self.after_sep = SpacedSeparator(Gtk.PositionType.BOTTOM)
예제 #10
0
파일: ruler.py 프로젝트: dimart/pitivi
    def __init__(self, timeline, hadj):
        Gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")

        self.timeline = timeline
        self._pipeline = None
        self.hadj = hadj
        hadj.connect("value-changed", self._hadjValueChangedCb)
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK |
                        Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK |
                        Gdk.EventMask.SCROLL_MASK)

        self.pixbuf = None

        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0

        self.position = 0  # In nanoseconds
        self.frame_rate = Gst.Fraction(1 / 1)
        self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND

        self.playhead_pixbuf = GdkPixbuf.Pixbuf.new_from_file(
            os.path.join(configure.get_pixmap_dir(), "pitivi-playhead.svg"))

        self.scales = SCALES
예제 #11
0
 def _zoomAdjustmentChangedCb(self, adjustment):
     # GTK crack
     self._updateZoomSlider = False
     Zoomable.setZoomLevel(int(adjustment.get_value()))
     self.timeline._scrollToPlayhead()
     self.zoomed_fitted = False
     self._updateZoomSlider = True
예제 #12
0
파일: previewers.py 프로젝트: davlem/pitivi
    def __init__(self, bElement):
        super(AudioPreviewer, self).__init__()
        PreviewGenerator.__init__(self, GES.TrackType.AUDIO)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.pipeline = None
        self.discovered = False
        self.bElement = bElement
        self.timeline = bElement.get_parent().get_timeline().ui

        self.nSamples = self.bElement.get_parent().get_asset().get_duration() / 10000000
        self._start = 0
        self._end = 0
        self._surface_x = 0

        # Guard against malformed URIs
        self._uri = quote_uri(bElement.props.uri)

        self._num_failures = 0
        self.adapter = None
        self.surface = None

        self._force_redraw = True

        self.bElement.connect("notify::in-point", self._inpointChangedCb)
예제 #13
0
파일: elements.py 프로젝트: dark-al/pitivi
    def __init__(self, bElement, track, timeline):
        """
        @param bElement : the backend GES.TrackElement
        @param track : the track to which the bElement belongs
        @param timeline : the containing graphic timeline.
        """
        Zoomable.__init__(self)
        Clutter.Actor.__init__(self)

        self.timeline = timeline
        self.bElement = bElement
        self.bElement.selected = Selected()
        self.bElement.ui_element = self
        self.track_type = self.bElement.get_track_type()  # This won't change
        self.isDragged = False
        self.lines = []
        self.keyframes = []
        self.source = None
        self.keyframedElement = None
        size = self.bElement.get_duration()

        self._createBackground(track)
        self._createPreview()
        self._createBorder()
        self._createMarquee()
        self._createHandles()
        self._createGhostclip()

        self.update(True)
        self.set_reactive(True)

        self.isSelected = False
        self._createMixingKeyframes()

        self._connectToEvents()
예제 #14
0
파일: ruler.py 프로젝트: GNOME/pitivi
    def __init__(self, timeline):
        Gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")

        self.timeline = timeline
        self._pipeline = None
        hadj = timeline.timeline.hadj
        hadj.connect("value-changed", self._hadj_value_changed_cb)
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK |
                        Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK |
                        Gdk.EventMask.SCROLL_MASK)

        self.pixbuf = None

        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0

        self.position = 0  # In nanoseconds
        self.frame_rate = Gst.Fraction(1 / 1)
        self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND

        self.scales = SCALES
예제 #15
0
파일: ruler.py 프로젝트: cymacs/pitivi
    def __init__(self, instance, hadj):
        gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")
        self.app = instance
        self._seeker = Seeker()
        self.hadj = hadj
        hadj.connect("value-changed", self._hadjValueChangedCb)
        self.add_events(gtk.gdk.POINTER_MOTION_MASK |
            gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK)

        self.pixbuf = None
        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0
        # This is the number of width we allocate for the pixbuf
        self.pixbuf_multiples = 4

        self.position = 0  # In nanoseconds
        self.pressed = False
        self.need_update = True
        self.min_frame_spacing = 5.0
        self.frame_height = 5.0
        self.frame_rate = gst.Fraction(1 / 1)
예제 #16
0
    def __init__(self, ges_elem, max_cpu_usage):
        Previewer.__init__(self, GES.TrackType.AUDIO, max_cpu_usage)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.pipeline = None
        self._wavebin = None

        self.ges_elem = ges_elem

        self.samples = None
        self.peaks = None
        self.surface = None
        # The zoom level when self.surface has been created.
        self._surface_zoom_level = 0
        # The samples range used when self.surface has been created.
        self._surface_start_ns = 0
        self._surface_end_ns = 0

        # Guard against malformed URIs
        self.wavefile = None
        self._uri = quote_uri(get_proxy_target(ges_elem).props.id)

        self._num_failures = 0
        self.become_controlled()
예제 #17
0
파일: ruler.py 프로젝트: jojva/pitivi
    def __init__(self, instance, hadj):
        Gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")
        self.app = instance
        self._seeker = Seeker()
        self.hadj = hadj
        hadj.connect("value-changed", self._hadjValueChangedCb)
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK |
            Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK |
            Gdk.EventMask.SCROLL_MASK)

        self.pixbuf = None

        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0
        # This is the number of width we allocate for the pixbuf
        self.pixbuf_multiples = 4

        self.position = 0  # In nanoseconds
        self.pressed = False
        self.min_frame_spacing = 5.0
        self.frame_height = 5.0
        self.frame_rate = Gst.Fraction(1 / 1)
        self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND
        self.connect('draw', self.drawCb)
        self.connect('configure-event', self.configureEventCb)
        self.callback_id = None
        self.callback_id_scroll = None
예제 #18
0
    def __init__(self, ges_elem, max_cpu_usage):
        Previewer.__init__(self, GES.TrackType.AUDIO, max_cpu_usage)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.pipeline = None
        self._wavebin = None

        self.discovered = False
        self.ges_elem = ges_elem

        asset = self.ges_elem.get_parent().get_asset()
        self.n_samples = asset.get_duration() / SAMPLE_DURATION
        self.samples = None
        self.peaks = None
        self._start = 0
        self._end = 0
        self._surface_x = 0

        # Guard against malformed URIs
        self.wavefile = None
        self._uri = quote_uri(get_proxy_target(ges_elem).props.id)

        self._num_failures = 0
        self.adapter = None
        self.surface = None

        self._force_redraw = True

        self.ges_elem.connect("notify::in-point", self._inpoint_changed_cb)
        self.connect("notify::height-request", self._height_changed_cb)
        self.become_controlled()
예제 #19
0
    def __init__(self, bElement, timeline):
        Clutter.Actor.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        PreviewGenerator.__init__(self, GES.TrackType.AUDIO)
        self.pipeline = None
        self.discovered = False
        self.bElement = bElement
        self._uri = quote_uri(bElement.props.uri)  # Guard against malformed URIs
        self.timeline = timeline
        self.actors = []

        self.set_content_scaling_filters(Clutter.ScalingFilter.NEAREST, Clutter.ScalingFilter.NEAREST)
        self.canvas = Clutter.Canvas()
        self.set_content(self.canvas)
        self.width = 0
        self._num_failures = 0
        self.lastUpdate = datetime.now()

        self.interval = timedelta(microseconds=INTERVAL)

        self.current_geometry = (-1, -1)

        self.adapter = None
        self.surface = None
        self.timeline.connect("scrolled", self._scrolledCb)
        self.canvas.connect("draw", self._drawContentCb)
        self.canvas.invalidate()

        self._callback_id = 0
예제 #20
0
파일: widgets.py 프로젝트: jojva/pitivi
 def _zoomAdjustmentChangedCb(self, adjustment):
     # GTK crack
     self._updateZoomSlider = False
     Zoomable.setZoomLevel(int(adjustment.get_value()))
     self.timeline._scrollToPlayhead()
     self.zoomed_fitted = False
     self._updateZoomSlider = True
예제 #21
0
    def __init__(self, bElement, timeline):
        Clutter.Actor.__init__(self)
        PreviewGenerator.__init__(self, GES.TrackType.AUDIO)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.pipeline = None
        self.discovered = False
        self.bElement = bElement
        self._uri = quote_uri(bElement.props.uri)  # Guard against malformed URIs
        self.timeline = timeline
        self.actors = []

        self.set_content_scaling_filters(Clutter.ScalingFilter.NEAREST, Clutter.ScalingFilter.NEAREST)
        self.canvas = Clutter.Canvas()
        self.set_content(self.canvas)
        self.width = 0
        self._num_failures = 0
        self.lastUpdate = None

        self.current_geometry = (-1, -1)

        self.adapter = None
        self.surface = None
        self.timeline.connect("scrolled", self._scrolledCb)
        self.canvas.connect("draw", self._drawContentCb)
        self.canvas.invalidate()

        self._callback_id = 0
예제 #22
0
파일: widgets.py 프로젝트: dimart/pitivi
    def _zoomAdjustmentChangedCb(self, adjustment):
        Zoomable.setZoomLevel(adjustment.get_value())
        self.timeline.app.write_action("set-zoom-level",
                                       {"level": adjustment.get_value(),
                                        "optional-action-type": True})

        if self._manual_set is False:
            self.timeline.timeline.scrollToPlayhead()
예제 #23
0
    def _zoomAdjustmentChangedCb(self, adjustment):
        Zoomable.setZoomLevel(adjustment.get_value())
        self.timeline.app.write_action("set-zoom-level",
                                       level=adjustment.get_value(),
                                       optional_action_type=True)

        if self._manual_set is False:
            self.timeline.timeline.scrollToPlayhead()
예제 #24
0
 def __init__(self, instance, element, height=46, **kwargs):
     super(Preview, self).__init__(**kwargs)
     Zoomable.__init__(self)
     self.app = instance
     self.height = float(height)
     self.element = element
     self.props.pointer_events = False
     # ghetto hack
     self.hadj = instance.gui.timeline_ui.hadj
예제 #25
0
    def __init__(self, timeline_container):
        Zoomable.__init__(self)
        ScaleRuler.__init__(self, self, self.app.settings,
                            self.app.gui.get_style_context())
        self.log("Creating new TimelineScaleRuler")

        self.timeline_container = timeline_container

        timeline_container.timeline.hadj.connect("value-changed",
                                                 self._hadj_value_changed_cb)
예제 #26
0
 def run(self):
     self.watchdog.start()
     if self.no_ui:
         self.instance.run(["--no-ui"])
     else:
         from pitivi.utils.timeline import Zoomable
         # set a common zoom ratio so that things like edge snapping values
         # are consistent
         Zoomable.setZoomLevel((3 * Zoomable.zoom_steps) / 4)
         self.instance.run([])
예제 #27
0
 def tearDown(self):
     # don't barf gc info all over the console if we have already failed a
     # test case
     if (self._num_failures < len(getattr(self._result, 'failures', [])) or
             self._num_errors < len(getattr(self._result, 'failures', []))):
         return
     if detect_leaks:
         self.gccollect()
         self.gcverify()
     Zoomable.setZoomLevel(self.__zoom_level)
예제 #28
0
파일: track.py 프로젝트: luisbg/PiTiVi
 def __init__(self, instance, track, timeline=None):
     GooCanvas.CanvasGroup.__init__(self)
     Zoomable.__init__(self)
     Loggable.__init__(self)
     self.app = instance
     self.widgets = {}
     self.transitions = []
     self.timeline = timeline
     self._track = None
     self.track = track
     self._expanded = True
예제 #29
0
 def __init__(self, container):
     Clutter.ScrollActor.__init__(self)
     Zoomable.__init__(self)
     self.bTimeline = None
     self._container = container
     self.elements = []
     self.ghostClips = []
     self.selection = Selection()
     self._scroll_point = Clutter.Point()
     self.lastPosition = 0  # Saved for redrawing when paused
     self._createPlayhead()
     self._createSnapIndicator()
예제 #30
0
    def render_cairo(self, cr, bounds, element, hscroll_pos, y1):
        if not self._view:
            return
        # The idea is to conceptually divide the clip into a sequence of
        # rectangles beginning at the start of the file, and
        # pixelsToNs(twidth) nanoseconds long. The thumbnail within the
        # rectangle is the frame produced from the timestamp corresponding to
        # rectangle's left edge. We speed things up by only drawing the
        # rectangles which intersect the given bounds.  FIXME: how would we
        # handle timestretch?
        height = bounds.y2 - bounds.y1
        width = bounds.x2 - bounds.x1

        # we actually draw the rectangles just to the left of the clip's in
        # point and just to the right of the clip's out-point, so we need to
        # mask off the actual bounds.
        cr.rectangle(bounds.x1, bounds.y1, width, height)
        cr.clip()

        # tdur = duration in ns of thumbnail
        # sof  = start of file in pixel coordinates
        x1 = bounds.x1
        sof = Zoomable.nsToPixel(element.get_start() - element.get_inpoint()) +\
            hscroll_pos

        # i = left edge of thumbnail to be drawn. We start with x1 and
        # subtract the distance to the nearest leftward rectangle.
        # Justification of the following:
        #                i = sof + k * twidth
        #                i = x1 - delta
        # sof + k * twidth = x1 - delta
        #           i * tw = (x1 - sof) - delta
        #    <=>     delta = x1 - sof (mod twidth).
        # Fortunately for us, % works on floats in python.

        i = x1 - ((x1 - sof) % (self.twidth + self._spacing()))

        # j = timestamp *within the element* of thumbnail to be drawn. we want
        # timestamps to be numerically stable, but in practice this seems to
        # give good enough results. It might be possible to improve this
        # further, which would result in fewer thumbnails needing to be
        # generated.
        j = Zoomable.pixelToNs(i - sof)
        istep = self.twidth + self._spacing()
        jstep = self.tdur + Zoomable.pixelToNs(self.spacing)

        while i < bounds.x2:
            self._thumbForTime(cr, j, i, y1)
            cr.rectangle(i - 1, y1, self.twidth + 2, self.theight)
            i += istep
            j += jstep
            cr.fill()
예제 #31
0
    def __init__(self, timeline, hadj):
        Gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")

        # Allows stealing focus from other GTK widgets, prevent accidents:
        self.props.can_focus = True
        self.connect("focus-in-event", self._focusInCb)
        self.connect("focus-out-event", self._focusOutCb)

        self.timeline = timeline
        self._background_color = timeline.get_style_context().lookup_color(
            'theme_bg_color')[1]
        self._seeker = Seeker()
        self.hadj = hadj
        hadj.connect("value-changed", self._hadjValueChangedCb)
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK
                        | Gdk.EventMask.BUTTON_PRESS_MASK
                        | Gdk.EventMask.BUTTON_RELEASE_MASK
                        | Gdk.EventMask.SCROLL_MASK)

        self.pixbuf = None

        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0
        # This is the number of width we allocate for the pixbuf
        self.pixbuf_multiples = 4

        self.position = 0  # In nanoseconds
        self.pressed = False
        self.frame_rate = Gst.Fraction(1 / 1)
        self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND
        self.connect('draw', self.drawCb)
        self.connect('configure-event', self.configureEventCb)
        self.callback_id = None
        self.callback_id_scroll = None
        self.set_size_request(0, HEIGHT)

        style = self.get_style_context()
        color_normal = style.get_color(Gtk.StateFlags.NORMAL)
        color_insensitive = style.get_color(Gtk.StateFlags.INSENSITIVE)
        self._color_normal = color_normal
        self._color_dimmed = Gdk.RGBA(
            *[(x * 3 + y * 2) / 5
              for x, y in ((color_normal.red, color_insensitive.red),
                           (color_normal.green, color_insensitive.green),
                           (color_normal.blue, color_insensitive.blue))])

        self.scales = SCALES
예제 #32
0
 def __init__(self, instance, element, interpolator, height=LAYER_HEIGHT_EXPANDED, **kwargs):
     super(Curve, self).__init__(**kwargs)
     View.__init__(self)
     Zoomable.__init__(self)
     self.app = instance
     self.keyframes = {}
     self.height = float(height)
     self.element = element
     # FIXME PyGI port
     #self.props.pointer_events = GooCanvas.EVENTS_STROKE
     self.interpolator = interpolator
     self._focused_kf = None
     self.normal()
     self.set_simple_transform(0, -KW_LABEL_Y_OVERFLOW, 1.0, 0)
예제 #33
0
파일: track.py 프로젝트: luisbg/PiTiVi
 def __init__(self, instance, element, timeline, **kwargs):
     self.app = instance
     self.element = element
     self.timeline = timeline
     self.movable = True
     self.current_pixbuf = TRIMBAR_PIXBUF
     GooCanvas.CanvasImage.__init__(self,
         pixbuf=self.current_pixbuf,
         line_width=0,
         pointer_events=GooCanvas.CanvasPointerEvents.FILL,
         **kwargs)
     View.__init__(self, instance, GES.EditMode.EDIT_TRIM)
     Zoomable.__init__(self)
     Loggable.__init__(self)
예제 #34
0
파일: track.py 프로젝트: cymacs/pitivi
 def __init__(self, instance, element, timeline, **kwargs):
     self.app = instance
     self.element = element
     self.timeline = timeline
     self.movable = True
     self.current_pixbuf = TRIMBAR_PIXBUF
     goocanvas.Image.__init__(self,
         pixbuf=self.current_pixbuf,
         line_width=0,
         pointer_events=goocanvas.EVENTS_FILL,
         **kwargs)
     View.__init__(self, instance, ges.EDIT_MODE_TRIM)
     Zoomable.__init__(self)
     Loggable.__init__(self)
예제 #35
0
 def _zoomSliderScrollCb(self, unused, event):
     delta = 0
     if event.direction in [Gdk.ScrollDirection.UP, Gdk.ScrollDirection.RIGHT]:
         delta = 1
     elif event.direction in [Gdk.ScrollDirection.DOWN, Gdk.ScrollDirection.LEFT]:
         delta = -1
     elif event.direction in [Gdk.ScrollDirection.SMOOTH]:
         unused_res, delta_x, delta_y = event.get_scroll_deltas()
         if delta_x:
             delta = math.copysign(1, delta_x)
         elif delta_y:
             delta = math.copysign(1, -delta_y)
     if delta:
         Zoomable.setZoomLevel(Zoomable.getCurrentZoomLevel() + delta)
예제 #36
0
파일: ruler.py 프로젝트: Jactry/pitivi
    def __init__(self, timeline, hadj):
        Gtk.DrawingArea.__init__(self)
        Zoomable.__init__(self)
        Loggable.__init__(self)
        self.log("Creating new ScaleRuler")

        # Allows stealing focus from other GTK widgets, prevent accidents:
        self.props.can_focus = True
        self.connect("focus-in-event", self._focusInCb)
        self.connect("focus-out-event", self._focusOutCb)

        self.timeline = timeline
        self._background_color = timeline.get_style_context().lookup_color(
            'theme_bg_color')[1]
        self._seeker = Seeker()
        self.hadj = hadj
        hadj.connect("value-changed", self._hadjValueChangedCb)
        self.add_events(Gdk.EventMask.POINTER_MOTION_MASK |
                        Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK |
                        Gdk.EventMask.SCROLL_MASK)

        self.pixbuf = None

        # all values are in pixels
        self.pixbuf_offset = 0
        self.pixbuf_offset_painted = 0
        # This is the number of width we allocate for the pixbuf
        self.pixbuf_multiples = 4

        self.position = 0  # In nanoseconds
        self.pressed = False
        self.frame_rate = Gst.Fraction(1 / 1)
        self.ns_per_frame = float(1 / self.frame_rate) * Gst.SECOND
        self.connect('draw', self.drawCb)
        self.connect('configure-event', self.configureEventCb)
        self.callback_id = None
        self.callback_id_scroll = None
        self.set_size_request(0, HEIGHT)

        style = self.get_style_context()
        color_normal = style.get_color(Gtk.StateFlags.NORMAL)
        color_insensitive = style.get_color(Gtk.StateFlags.INSENSITIVE)
        self._color_normal = color_normal
        self._color_dimmed = Gdk.RGBA(
            *[(x * 3 + y * 2) / 5
              for x, y in ((color_normal.red, color_insensitive.red),
                           (color_normal.green, color_insensitive.green),
                           (color_normal.blue, color_insensitive.blue))])

        self.scales = SCALES
예제 #37
0
파일: curve.py 프로젝트: cymacs/pitivi
 def __init__(self, instance, element, interpolator, height=LAYER_HEIGHT_EXPANDED,
     **kwargs):
     super(Curve, self).__init__(**kwargs)
     View.__init__(self)
     Zoomable.__init__(self)
     self.app = instance
     self.keyframes = {}
     self.height = float(height)
     self.element = element
     self.props.pointer_events = goocanvas.EVENTS_STROKE
     self.interpolator = interpolator
     self._focused_kf = None
     self.normal()
     self.set_simple_transform(0, -KW_LABEL_Y_OVERFLOW, 1.0, 0)
예제 #38
0
파일: widgets.py 프로젝트: dimart/pitivi
 def _zoomSliderScrollCb(self, unused, event):
     delta = 0
     if event.direction in [Gdk.ScrollDirection.UP, Gdk.ScrollDirection.RIGHT]:
         delta = 1
     elif event.direction in [Gdk.ScrollDirection.DOWN, Gdk.ScrollDirection.LEFT]:
         delta = -1
     elif event.direction in [Gdk.ScrollDirection.SMOOTH]:
         unused_res, delta_x, delta_y = event.get_scroll_deltas()
         if delta_x:
             delta = math.copysign(1, delta_x)
         elif delta_y:
             delta = math.copysign(1, -delta_y)
     if delta:
         Zoomable.setZoomLevel(Zoomable.getCurrentZoomLevel() + delta)
예제 #39
0
파일: ruler.py 프로젝트: davlem/pitivi
 def do_scroll_event(self, event):
     if event.scroll.state & Gdk.ModifierType.CONTROL_MASK:
         # Control + scroll = zoom
         if event.scroll.direction == Gdk.ScrollDirection.UP:
             Zoomable.zoomIn()
         elif event.scroll.direction == Gdk.ScrollDirection.DOWN:
             Zoomable.zoomOut()
     else:
         # No modifier key held down, just scroll
         if event.scroll.direction in (Gdk.ScrollDirection.UP,
                                       Gdk.ScrollDirection.LEFT):
             self.timeline.scroll_left()
         elif event.scroll.direction in (Gdk.ScrollDirection.DOWN,
                                         Gdk.ScrollDirection.RIGHT):
             self.timeline.scroll_right()
예제 #40
0
    def __init__(self, bElement, timeline):
        Zoomable.__init__(self)
        Clutter.Actor.__init__(self)

        self.timeline = timeline
        self.bElement = bElement
        self.bElement.selected = Selected()
        self.bElement.ui_element = weakref.proxy(self)
        self.track_type = self.bElement.get_track_type()  # This won't change
        self.isDragged = False
        self.lines = []
        self.keyframes = []
        self.keyframesVisible = False
        self.source = None
        self.keyframedElement = None
        self.rightHandle = None
        self.isSelected = False
        self.updating_keyframes = False
        size = self.bElement.get_duration()

        self.background = self._createBackground()
        self.background.set_position(1, 1)
        self.add_child(self.background)

        self.preview = self._createPreview()
        self.add_child(self.preview)

        self.border = self._createBorder()
        self.add_child(self.border)

        self.set_child_below_sibling(self.border, self.background)

        self.marquee = self._createMarquee()
        self.add_child(self.marquee)

        self._createHandles()

        self._linesMarker = self._createMarker()
        self._keyframesMarker = self._createMarker()

        self._createGhostclip()

        self.update(True)
        self.set_reactive(True)

        self._createMixingKeyframes()

        self._connectToEvents()
예제 #41
0
파일: elements.py 프로젝트: Jactry/pitivi
    def __init__(self, bElement, timeline):
        Zoomable.__init__(self)
        Clutter.Actor.__init__(self)

        self.timeline = timeline
        self.bElement = bElement
        self.bElement.selected = Selected()
        self.bElement.ui_element = weakref.proxy(self)
        self.track_type = self.bElement.get_track_type()  # This won't change
        self.isDragged = False
        self.lines = []
        self.keyframes = []
        self.keyframesVisible = False
        self.source = None
        self.keyframedElement = None
        self.rightHandle = None
        self.isSelected = False
        self.updating_keyframes = False
        size = self.bElement.get_duration()

        self.background = self._createBackground()
        self.background.set_position(1, 1)
        self.add_child(self.background)

        self.preview = self._createPreview()
        self.add_child(self.preview)

        self.border = self._createBorder()
        self.add_child(self.border)

        self.set_child_below_sibling(self.border, self.background)

        self.marquee = self._createMarquee()
        self.add_child(self.marquee)

        self._createHandles()

        self._linesMarker = self._createMarker()
        self._keyframesMarker = self._createMarker()

        self._createGhostclip()

        self.update(True)
        self.set_reactive(True)

        self._createMixingKeyframes()

        self._connectToEvents()
예제 #42
0
파일: elements.py 프로젝트: Jactry/pitivi
    def updateValue(self, delta_x, delta_y):
        newTs = self.tsStart + Zoomable.pixelToNs(delta_x)
        newValue = self.valueStart - (delta_y / EXPANDED_SIZE)

        # Don't overlap first and last keyframes.
        newTs = min(max(newTs, self.inpoint + 1),
                    self.duration + self.inpoint - 1)

        newValue = min(max(newValue, 0.0), 1.0)

        if not self.has_changeable_time:
            newTs = self.lastTs

        updating = self.timelineElement.updating_keyframes
        self.timelineElement.updating_keyframes = True
        self.timelineElement.source.unset(self.lastTs)
        if (self.timelineElement.source.set(newTs, newValue)):
            self.value = Gst.TimedValue()
            self.value.timestamp = newTs
            self.value.value = newValue
            self.lastTs = newTs

            self.timelineElement.setKeyframePosition(self, self.value)
            # Resort the keyframes list each time. Should be cheap as there should never be too much keyframes,
            # if optimization is needed, check if resorting is needed, should
            # not be in 99 % of the cases.
            self.timelineElement.keyframes = sorted(
                self.timelineElement.keyframes, key=lambda keyframe: keyframe.value.timestamp)
            self.timelineElement.drawLines(self.line)
            # This will update the viewer. nifty.
            if not self.line:
                self.timelineElement.timeline._container.seekInPosition(
                    newTs + self.start)

        self.timelineElement.updating_keyframes = updating
예제 #43
0
    def updateValue(self, delta_x, delta_y):
        newTs = self.tsStart + Zoomable.pixelToNs(delta_x)
        newValue = self.valueStart - (delta_y / EXPANDED_SIZE)

        # Don't overlap first and last keyframes.
        newTs = min(max(newTs, self.inpoint + 1), self.duration + self.inpoint - 1)

        newValue = min(max(newValue, 0.0), 1.0)

        if not self.has_changeable_time:
            newTs = self.lastTs

        self.timelineElement.source.unset(self.lastTs)
        if (self.timelineElement.source.set(newTs, newValue)):
            self.value = Gst.TimedValue()
            self.value.timestamp = newTs
            self.value.value = newValue
            self.lastTs = newTs

            self.timelineElement.setKeyframePosition(self, self.value)
            # Resort the keyframes list each time. Should be cheap as there should never be too much keyframes,
            # if optimization is needed, check if resorting is needed, should not be in 99 % of the cases.
            self.timelineElement.keyframes = sorted(self.timelineElement.keyframes, key=lambda keyframe: keyframe.value.timestamp)
            self.timelineElement.drawLines(self.line)
            # This will update the viewer. nifty.
            if not self.line:
                self.timelineElement.timeline._container.seekInPosition(newTs + self.start)
예제 #44
0
    def _startThumbnailing(self):
        if not self.pipeline:
            # Can happen if stopGeneration is called because the clip has been
            # removed from the timeline after the PreviewGeneratorManager
            # started this job.
            return
        self.debug('Now generating thumbnails for: %s',
                   filename_from_uri(self.uri))
        query_success, duration = self.pipeline.query_duration(Gst.Format.TIME)
        if not query_success or duration == -1:
            self.debug("Could not determine duration of: %s", self.uri)
            duration = self.duration
        else:
            self.duration = duration

        self.queue = list(range(0, duration, self.thumb_period))

        self._checkCPU()

        if self.bElement.props.in_point != 0:
            position = Clutter.Point()
            position.x = Zoomable.nsToPixel(self.bElement.props.in_point)
            self.scroll_to_point(position)
        self._addVisibleThumbnails()
        # Save periodically to avoid the common situation where the user exits
        # the app before a long clip has been fully thumbnailed.
        # Spread timeouts between 30-80 secs to avoid concurrent disk writes.
        random_time = randrange(30, 80)
        GLib.timeout_add_seconds(random_time, self._autosave)

        # Remove the GSource
        return False
예제 #45
0
 def do_simple_update(self, cr):
     cr.identity_matrix()
     if issubclass(self.previewer.__class__, RandomAccessPreviewer):
         border_width = self.previewer._spacing()
         self.bounds = goocanvas.Bounds(border_width, 4,
         max(0, Zoomable.nsToPixel(self.element.get_duration()) -
             border_width), self.height)
예제 #46
0
    def _update_thumbnails(self):
        """Updates the thumbnail widgets for the clip at the current zoom."""
        if not self.thumb_width:
            # The __image_pixbuf is not ready yet.
            return

        thumbs = {}
        interval = self.thumb_interval(self.thumb_width)
        element_left = quantize(self.ges_elem.props.in_point, interval)
        element_right = self.ges_elem.props.in_point + self.ges_elem.props.duration
        y = (self.props.height_request - self.thumb_height) / 2
        for position in range(element_left, element_right, interval):
            x = Zoomable.nsToPixel(position) - self.nsToPixel(
                self.ges_elem.props.in_point)
            try:
                thumb = self.thumbs.pop(position)
                self.move(thumb, x, y)
            except KeyError:
                thumb = Thumbnail(self.thumb_width, self.thumb_height)
                self.put(thumb, x, y)

            thumbs[position] = thumb
            thumb.set_from_pixbuf(self.__image_pixbuf)
            thumb.set_visible(True)

        for thumb in self.thumbs.values():
            self.remove(thumb)
        self.thumbs = thumbs
예제 #47
0
    def __init__(self, instance, uri):
        RandomAccessPreviewer.__init__(self, instance, uri)
        self.tstep = Zoomable.pixelToNsAt(self.twidth, Zoomable.max_zoom)

        if self.framerate.num:
            frame_duration = (gst.SECOND * self.framerate.denom) / self.framerate.num
            self.tstep = max(frame_duration, self.tstep)
예제 #48
0
    def convertGhostClips(self):
        for ghostCouple in self.ghostClips:
            ghostclip = ghostCouple[0]
            if not ghostclip:
                ghostclip = ghostCouple[1]

            layer = None
            target = None

            if ghostclip.shouldCreateLayer:
                layer = self.insertLayer(ghostclip)
                target = layer
            else:
                for layer in self.bTimeline.get_layers():
                    if layer.get_priority() == ghostclip.priority:
                        target = layer
                        break

            if target is None:
                layer = self.bTimeline.append_layer()

            layer.add_asset(ghostclip.asset,
                            Zoomable.pixelToNs(ghostclip.props.x),
                            0,
                            ghostclip.asset.get_duration(),
                            ghostclip.asset.get_supported_formats())
예제 #49
0
    def zoomChanged(self):
        if self._settings and self.bTimeline:
            # zoomChanged might be called various times before the UI is ready
            self.bTimeline.props.snapping_distance = \
                Zoomable.pixelToNs(self._settings.edgeSnapDeadband)

        self.updateHScrollAdjustments()
예제 #50
0
 def _createGhostclip(self, trackType, asset):
     ghostclip = Ghostclip(trackType)
     ghostclip.asset = asset
     ghostclip.setNbrLayers(len(self.bTimeline.get_layers()))
     ghostclip.setWidth(Zoomable.nsToPixel(asset.get_duration()))
     self.add_child(ghostclip)
     return ghostclip
예제 #51
0
def _releaseButtonIfNeeded(scenario, action, timeline, container, edge, layer_prio,
                           position, y):
    try:
        next_actions = scenario.get_actions()
        for next_action in next_actions[1:]:
            if next_action.type not in ["wait", "add-layer"]:
                break
    except KeyError:
        return

    need_release = True
    if next_action and next_action.type == "edit-container":
        edge = get_edge(next_action.structure)

        if edge == scenario.last_edge:
            need_release = False

    if next_action is None or need_release:
        scenario.dragging = False
        x = Zoomable.nsToPixelAccurate(position)
        event = Event(Gdk.EventType.BUTTON_RELEASE, button=1, x=x, y=y)
        with mock.patch.object(Gtk, "get_event_widget") as get_event_widget:
            get_event_widget.return_value = container.ui
            container.ui._button_release_event_cb(None, event)

        if layer_prio > 0 and container.get_layer().get_priority() != layer_prio:
            scenario.report_simple(GLib.quark_from_string("scenario::execution-error"),
                                   "Resulting clip priority: %s"
                                   " is not the same as the wanted one: %s"
                                   % (container.get_layer().get_priority(),
                                      layer_prio))

        cleanEditModes(timeline, scenario)
예제 #52
0
    def _addVisibleThumbnails(self, rect):
        """Gets the thumbnails for the currently visible clip portion."""
        if self.thumb_width is None:
            return False

        self.thumbs = {}
        self.wishlist = []

        thumb_duration = self._get_thumb_duration()

        element_left = self.pixelToNs(rect.x) + self.ges_elem.props.in_point
        element_right = element_left + self.pixelToNs(rect.width)
        element_left = quantize(element_left, thumb_duration)

        for current_time in range(element_left, element_right, thumb_duration):
            thumb = Thumbnail(self.thumb_width, self.thumb_height)
            x = Zoomable.nsToPixel(current_time) - self.nsToPixel(
                self.ges_elem.props.in_point)
            y = (self.props.height_request - self.thumb_height) / 2
            self.put(thumb, x, y)

            self.thumbs[current_time] = thumb
            if self.__image_pixbuf:
                thumb.set_from_pixbuf(self.__image_pixbuf)
                thumb.set_visible(True)
            elif current_time in self.thumb_cache:
                pixbuf = self.thumb_cache[current_time]
                thumb.set_from_pixbuf(pixbuf)
                thumb.set_visible(True)
            else:
                self.wishlist.append(current_time)

        return True
예제 #53
0
파일: previewers.py 프로젝트: dz0ny/pitivi
    def _addVisibleThumbnails(self, rect):
        """Gets the thumbnails for the currently visible clip portion."""
        if self.thumb_width is None:
            return False

        self.thumbs = {}
        self.wishlist = []

        thumb_duration = self._get_thumb_duration()

        element_left = self.pixelToNs(rect.x) + self.ges_elem.props.in_point
        element_right = element_left + self.pixelToNs(rect.width)
        element_left = quantize(element_left, thumb_duration)

        for current_time in range(element_left, element_right, thumb_duration):
            thumb = Thumbnail(self.thumb_width, self.thumb_height)
            x = Zoomable.nsToPixel(current_time) - self.nsToPixel(self.ges_elem.props.in_point)
            y = (self.props.height_request - self.thumb_height) / 2
            self.put(thumb, x, y)

            self.thumbs[current_time] = thumb
            if self.__image_pixbuf:
                thumb.set_from_pixbuf(self.__image_pixbuf)
                thumb.set_visible(True)
            elif current_time in self.thumb_cache:
                pixbuf = self.thumb_cache[current_time]
                thumb.set_from_pixbuf(pixbuf)
                thumb.set_visible(True)
            else:
                self.wishlist.append(current_time)

        return True
예제 #54
0
    def _addVisibleThumbnails(self):
        """
        Get the thumbnails to be displayed in the currently visible clip portion
        """
        self.remove_all_children()
        old_thumbs = self.thumbs
        self.thumbs = {}
        self.wishlist = []

        thumb_duration = self._get_thumb_duration()
        element_left, element_right = self._get_visible_range()
        element_left = quantize(element_left, thumb_duration)

        for current_time in range(element_left, element_right, thumb_duration):
            thumb = Thumbnail(self.thumb_width, self.thumb_height)
            thumb.set_position(Zoomable.nsToPixel(current_time), THUMB_MARGIN_PX)
            self.add_child(thumb)
            self.thumbs[current_time] = thumb
            if current_time in self.thumb_cache:
                gdkpixbuf = self.thumb_cache[current_time]
                if self._allAnimated or current_time not in old_thumbs:
                    self.thumbs[current_time].set_from_gdkpixbuf_animated(gdkpixbuf)
                else:
                    self.thumbs[current_time].set_from_gdkpixbuf(gdkpixbuf)
            else:
                self.wishlist.append(current_time)
        self._allAnimated = False
예제 #55
0
    def _addVisibleThumbnails(self):
        """
        Get the thumbnails to be displayed in the currently visible clip portion
        """
        self.remove_all_children()
        old_thumbs = self.thumbs
        self.thumbs = {}
        self.wishlist = []

        thumb_duration = self._get_thumb_duration()
        element_left, element_right = self._get_visible_range()
        element_left = quantize(element_left, thumb_duration)

        for current_time in range(element_left, element_right, thumb_duration):
            thumb = Thumbnail(self.thumb_width, self.thumb_height)
            thumb.set_position(Zoomable.nsToPixel(current_time), self.thumb_margin)
            self.add_child(thumb)
            self.thumbs[current_time] = thumb
            if current_time in self.thumb_cache:
                gdkpixbuf = self.thumb_cache[current_time]
                if self._allAnimated or current_time not in old_thumbs:
                    self.thumbs[current_time].set_from_gdkpixbuf_animated(gdkpixbuf)
                else:
                    self.thumbs[current_time].set_from_gdkpixbuf(gdkpixbuf)
            else:
                self.wishlist.append(current_time)
        self._allAnimated = False
예제 #56
0
    def __init__(self, ges_elem, max_cpu_usage):
        Previewer.__init__(self, GES.TrackType.VIDEO, max_cpu_usage)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        # Variables related to the timeline objects
        self.timeline = ges_elem.get_parent().get_timeline().ui
        self.ges_elem = ges_elem

        # Guard against malformed URIs
        self.uri = quote_uri(get_proxy_target(ges_elem).props.id)

        self.__preroll_timeout_id = 0

        # Variables related to thumbnailing
        self.wishlist = []
        self.queue = []
        self._thumb_cb_id = None
        self._running = False

        # We should have one thumbnail per thumb_period.
        # TODO: get this from the user settings
        self.thumb_period = int(0.5 * Gst.SECOND)
        self.thumb_height = THUMB_HEIGHT

        self.__image_pixbuf = None
        if isinstance(ges_elem, GES.ImageSource):
            self.__image_pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
                Gst.uri_get_location(self.uri), -1, self.thumb_height, True)

        self.thumbs = {}
        self.thumb_cache = ThumbnailCache.get(self.uri)
        self._ensure_proxy_thumbnails_cache()
        self.thumb_width, unused_height = self.thumb_cache.getImagesSize()

        self.cpu_usage_tracker = CPUUsageTracker()
        self.interval = 500  # Every 0.5 second, reevaluate the situation

        # Connect signals and fire things up
        self.ges_elem.connect("notify::in-point", self._inpoint_changed_cb)

        self.pipeline = None
        self.gdkpixbufsink = None
        self.becomeControlled()

        self.connect("notify::height-request", self._height_changed_cb)