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)
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)
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)])
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()
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
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()
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()
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()
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
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
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)
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()
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)
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()
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
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()
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
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
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()
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()
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
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)
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([])
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)
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
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()
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()
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
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)
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)
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)
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)
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)
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()
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()
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
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)
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
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)
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
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)
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())
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()
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
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)
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
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
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
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
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)