def clipTrimPreview(self, tl_obj, position): """ While a clip is being trimmed, show a live preview of it. """ if isinstance(tl_obj, GES.TitleClip) or tl_obj.props.is_image or not hasattr( tl_obj, "get_uri"): self.log("%s is an image or has no URI, so not previewing trim" % tl_obj) return False clip_uri = tl_obj.props.uri cur_time = time() if self.pipeline == self.app.project_manager.current_project.pipeline: self.debug("Creating temporary pipeline for clip %s, position %s", clip_uri, format_ns(position)) self._oldTimelinePos = self.pipeline.getPosition() self.setPipeline(AssetPipeline(tl_obj)) self._lastClipTrimTime = cur_time if (cur_time - self._lastClipTrimTime ) > 0.2 and self.pipeline.getState() == Gst.State.PAUSED: # Do not seek more than once every 200 ms (for performance) self.pipeline.simple_seek(position) self._lastClipTrimTime = cur_time
def get_trim_preview_pipeline(self, uri): try: trim_pipeline, sink_widget = self.trim_pipelines_cache[uri] self.debug("Reusing temporary pipeline for clip %s", uri) except KeyError: self.debug("Creating temporary pipeline for clip %s", uri) trim_pipeline = AssetPipeline(uri) unused_video_sink, sink_widget = trim_pipeline.create_sink() self.trim_pipelines_cache[uri] = trim_pipeline, sink_widget if len(self.trim_pipelines_cache) > 4: # Pop the first inserted item. expired_uri, ( expired_pipeline, unused_expired_widget) = self.trim_pipelines_cache.popitem( last=False) self.debug("Releasing temporary pipeline for clip %s", expired_uri) expired_pipeline.release() return trim_pipeline, sink_widget
def clipTrimPreview(self, clip, position): """Shows a live preview of a clip being trimmed.""" if not hasattr(clip, "get_uri") or isinstance(clip, GES.TitleClip) or clip.props.is_image: self.log( "%s is an image or has no URI, so not previewing trim" % clip) return False clip_uri = clip.props.uri cur_time = time() if self.pipeline == self.app.project_manager.current_project.pipeline: self.debug("Creating temporary pipeline for clip %s, position %s", clip_uri, format_ns(position)) self._oldTimelinePos = self.pipeline.getPosition(False) self.pipeline.set_state(Gst.State.NULL) self.setPipeline(AssetPipeline(clip)) self.__owning_pipeline = True self._lastClipTrimTime = cur_time if (cur_time - self._lastClipTrimTime) > 0.2 and self.pipeline.getState() == Gst.State.PAUSED: # Do not seek more than once every 200 ms (for performance) self.pipeline.simple_seek(position) self._lastClipTrimTime = cur_time
def __init__(self, settings, minimal=False, discover_sync=False): Gtk.Grid.__init__(self) Loggable.__init__(self) self.log("Init PreviewWidget") self.settings = settings self.error_message = None # playbin for play pics self.player = AssetPipeline(name="preview-player") self.player.connect('eos', self._pipeline_eos_cb) self.player.connect('error', self._pipeline_error_cb) self.player._bus.connect('message::tag', self._tag_found_cb) # some global variables for preview handling self.is_playing = False self.at_eos = False self.original_dims = (PREVIEW_WIDTH, PREVIEW_HEIGHT) self.countinuous_seek = False self.slider_being_used = False self.current_selected_uri = "" self.current_preview_type = "" self.play_on_discover = False self.description = "" # Gui elements: # Drawing area for video output unused_sink, sink_widget = self.player.create_sink() self.preview_video = ViewerWidget(sink_widget) self.preview_video.props.hexpand = minimal self.preview_video.props.vexpand = minimal self.preview_video.show_all() self.attach(self.preview_video, 0, 0, 1, 1) # An image for images and audio self.preview_image = Gtk.Image() self.preview_image.set_size_request(self.settings.FCpreviewWidth, self.settings.FCpreviewHeight) self.preview_image.show() self.attach(self.preview_image, 0, 1, 1, 1) # Play button self.bbox = Gtk.Box() self.bbox.set_orientation(Gtk.Orientation.HORIZONTAL) self.play_button = Gtk.ToolButton() self.play_button.set_icon_name("media-playback-start") self.play_button.connect("clicked", self._on_start_stop_clicked_cb) self.bbox.pack_start(self.play_button, False, False, 0) # Scale for position handling self.pos_adj = Gtk.Adjustment() self.seeker = Gtk.Scale.new(Gtk.Orientation.HORIZONTAL, self.pos_adj) self.seeker.connect('button-press-event', self._on_seeker_press_cb) self.seeker.connect('button-release-event', self._on_seeker_press_cb) self.seeker.connect('motion-notify-event', self._on_motion_notify_cb) self.seeker.set_draw_value(False) self.seeker.show() self.bbox.pack_start(self.seeker, True, True, 0) # Zoom buttons self.b_zoom_in = Gtk.ToolButton() self.b_zoom_in.set_icon_name("zoom-in") self.b_zoom_in.connect("clicked", self._on_zoom_clicked_cb, 1) self.b_zoom_out = Gtk.ToolButton() self.b_zoom_out.set_icon_name("zoom-out") self.b_zoom_out.connect("clicked", self._on_zoom_clicked_cb, -1) self.bbox.pack_start(self.b_zoom_in, False, False, 0) self.bbox.pack_start(self.b_zoom_out, False, False, 0) self.bbox.show_all() self.attach(self.bbox, 0, 2, 1, 1) # Label for metadata tags self.l_tags = Gtk.Label() self.l_tags.set_justify(Gtk.Justification.LEFT) self.l_tags.set_ellipsize(Pango.EllipsizeMode.END) self.l_tags.show() self.attach(self.l_tags, 0, 3, 1, 1) # Error handling vbox = Gtk.Box() vbox.set_orientation(Gtk.Orientation.VERTICAL) vbox.set_spacing(SPACING) self.l_error = Gtk.Label(label=_("Pitivi can not preview this file.")) self.b_details = Gtk.Button.new_with_label(_("More info")) self.b_details.connect('clicked', self._on_b_details_clicked_cb) vbox.pack_start(self.l_error, True, True, 0) vbox.pack_start(self.b_details, False, False, 0) vbox.show() self.attach(vbox, 0, 4, 1, 1) if minimal: self.remove(self.l_tags) self.bbox.remove(self.b_zoom_in) self.bbox.remove(self.b_zoom_out) self.clear_preview() self._discover_sync = discover_sync