Beispiel #1
0
    def _setScenarioFile(self, uri):
        if 'PITIVI_SCENARIO_FILE' in os.environ:
            uri = quote_uri(os.environ['PITIVI_SCENARIO_FILE'])
        else:
            cache_dir = get_dir(os.path.join(xdg_cache_home(), "scenarios"))
            scenario_name = str(time.strftime("%Y%m%d-%H%M%S"))
            project_path = None
            if uri:
                project_path = path_from_uri(uri)
                scenario_name += os.path.splitext(
                    project_path.replace(os.sep, "_"))[0]

            uri = os.path.join(cache_dir, scenario_name + ".scenario")
            uri = quote_uri(uri)

        self._scenario_file = open(path_from_uri(uri), "w")

        if project_path:
            f = open(project_path)
            content = f.read()
            if not uri.endswith(".scenario"):
                self.write_action(
                    "load-project",
                    {"serialized-content": "%s" % content.replace("\n", "")})
            f.close()
Beispiel #2
0
    def _set_scenario_file(self, uri):
        if uri:
            project_path = path_from_uri(uri)
        else:
            # New project.
            project_path = None
        if 'PITIVI_SCENARIO_FILE' in os.environ:
            scenario_path = os.environ['PITIVI_SCENARIO_FILE']
        else:
            cache_dir = xdg_cache_home("scenarios")
            scenario_name = str(time.strftime("%Y%m%d-%H%M%S"))
            if project_path:
                scenario_name += os.path.splitext(
                    project_path.replace(os.sep, "_"))[0]
            scenario_path = os.path.join(cache_dir,
                                         scenario_name + ".scenario")

        scenario_path = path_from_uri(quote_uri(scenario_path))
        self._scenario_file = open(scenario_path, "w")

        if project_path and not project_path.endswith(".scenario"):
            # It's an xges file probably.
            with open(project_path) as project:
                content = project.read().replace("\n", "")
                self.write_action("load-project", serialized_content=content)
Beispiel #3
0
    def addUris(self, uris):
        """
        Add c{uris} to the source list.

        The uris will be analyzed before being added.
        """
        self.emit("starting")
        self.debug("Adding %s", uris)
        self.nb_files_to_import += len(uris)
        for uri in uris:
            # Ensure we have a correctly encoded URI according to RFC 2396.
            # Otherwise, in some cases we'd get rogue characters that break
            # searching for duplicates
            uri = quote_uri(uri)
            if uri not in self._sources:
                self.discoverer.discover_uri_async(uri)
                self.debug("Added a uri to discoverer async")
            else:
                self.nb_files_to_import -= 1
                self.debug('"%s" is already in the media library' % uri)
        if self.nb_files_to_import == 0:
            # This is a cornercase hack for when you try to import a bunch of
            # clips that are all present in the media library already.
            # This will allow the progressbar to hide.
            self.emit("nothing-to-import")
        else:
            self.debug("Done adding all URIs to discoverer async")
Beispiel #4
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
Beispiel #5
0
    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)
Beispiel #6
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()
Beispiel #7
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)
Beispiel #8
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
Beispiel #9
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()
Beispiel #10
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()
Beispiel #11
0
    def saveProject(self, project, uri=None, overwrite=False, formatter=None, backup=False):
        """
        Save the L{Project} to the given location.

        If specified, use the given formatter.

        @type project: L{Project}
        @param project: The L{Project} to save.
        @type uri: L{str}
        @param uri: The absolute URI of the location to store the project to.
        @param overwrite: Whether to overwrite existing location.
        @type overwrite: C{bool}
        @type formatter: L{Formatter}
        @param formatter: The L{Formatter} to use to store the project if specified.
        If it is not specified, then it will be saved at its original format.
        @param backup: Whether the requested save operation is for a backup
        @type backup: C{bool}

        @see: L{Formatter.saveProject}
        """
        if formatter is None:
            formatter = ges.PitiviFormatter()
        if backup:
            if project.uri and self.current.uri is not None:
                # Ignore whatever URI that is passed on to us. It's a trap.
                uri = self._makeBackupURI(project.uri)
            else:
                # Do not try to save backup files for blank projects.
                # It is possible that self.current.uri == None when the backup
                # timer sent us an old instance of the (now closed) project.
                return
        elif uri is None:
            # This allows calling saveProject without specifying the target URI
            uri = project.uri
        else:
            # Ensure the URI we are given is properly encoded, or GIO will fail
            uri = quote_uri(uri)
            # Update the project instance's uri for the "Save as" scenario.
            # Otherwise, subsequent saves will be to the old uri.
            if not backup:
                project.uri = uri
        if uri is None or not ges.formatter_can_save_uri(uri):
            self.emit("save-project-failed", project, uri)
            return

        # FIXME Using query_exist is not the best thing to do, but makes
        # the trick for now
        file = gio.File(uri)
        if overwrite or not file.query_exist():
            formatter.set_sources(project.medialibrary.getSources())
            saved = formatter.save_to_uri(project.timeline, uri)
            if saved:
                if not backup:
                    # Do not emit the signal when autosaving a backup file
                    self.emit("project-saved", project, uri)
                    self.debug('Saved project "%s"' % uri)
                else:
                    self.debug('Saved backup "%s"' % uri)
            return saved
Beispiel #12
0
 def openCb(self, unused_app, giofiles, unused_count, unused_hint):
     assert giofiles
     self.createMainWindow()
     if len(giofiles) > 1:
         self.warning("Can open only one project file at a time. Ignoring the rest!")
     project_file = giofiles[0]
     self.project_manager.loadProject(quote_uri(project_file.get_uri()))
     return True
Beispiel #13
0
    def _addAsset(self, asset):
        # 128 is the normal size for thumbnails, but for *icons* it looks insane
        LARGE_SIZE = 96
        info = asset.get_info()

        # The code below tries to read existing thumbnails from the freedesktop
        # thumbnails directory (~/.thumbnails). The filenames are simply
        # the file URI hashed with md5, so we can retrieve them easily.
        video_streams = [i for i in info.get_stream_list() if isinstance(i, DiscovererVideoInfo)]
        if len(video_streams) > 0:
            # From the freedesktop spec: "if the environment variable
            # $XDG_CACHE_HOME is set and not blank then the directory
            # $XDG_CACHE_HOME/thumbnails will be used, otherwise
            # $HOME/.cache/thumbnails will be used."
            # Older version of the spec also mentioned $HOME/.thumbnails
            quoted_uri = quote_uri(info.get_uri())
            thumbnail_hash = md5(quoted_uri).hexdigest()
            try:
                thumb_dir = os.environ['XDG_CACHE_HOME']
                thumb_64, thumb_128 = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            except KeyError:
                thumb_64, thumb_128 = (None, None)
            if thumb_64 is None:
                thumb_dir = os.path.expanduser("~/.cache/thumbnails/")
                thumb_64, thumb_128 = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            if thumb_64 is None:
                thumb_dir = os.path.expanduser("~/.thumbnails/")
                thumb_64, thumb_128 = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            if thumb_64 is None:
                if asset.is_image():
                    thumb_64 = self._getIcon("image-x-generic")
                    thumb_128 = self._getIcon("image-x-generic", None, LARGE_SIZE)
                else:
                    thumb_64 = self._getIcon("video-x-generic")
                    thumb_128 = self._getIcon("video-x-generic", None, LARGE_SIZE)
                # TODO ideally gst discoverer should create missing thumbnails.
                self.log("Missing a thumbnail for %s, queuing", path_from_uri(quoted_uri))
                self._missing_thumbs.append(quoted_uri)
        else:
            thumb_64 = self._getIcon("audio-x-generic")
            thumb_128 = self._getIcon("audio-x-generic", None, LARGE_SIZE)

        if info.get_duration() == Gst.CLOCK_TIME_NONE:
            duration = ''
        else:
            duration = beautify_length(info.get_duration())

        name = info_name(info)

        self.pending_rows.append((thumb_64,
                                  thumb_128,
                                  beautify_info(info),
                                  asset,
                                  info.get_uri(),
                                  duration,
                                  name))
        if len(self.pending_rows) > 50:
            self.flush_pending_rows()
Beispiel #14
0
 def do_open(self, giofiles, unused_count, unused_hint):
     assert giofiles
     self.create_main_window()
     if len(giofiles) > 1:
         self.warning(
             "Opening only one project at a time. Ignoring the rest!")
     project_file = giofiles[0]
     self.project_manager.load_project(quote_uri(project_file.get_uri()))
     return True
Beispiel #15
0
 def openCb(self, unused_app, giofiles, unused_count, unused_hint):
     assert giofiles
     self.createMainWindow()
     if len(giofiles) > 1:
         self.warning(
             "Can open only one project file at a time. Ignoring the rest!")
     project_file = giofiles[0]
     self.project_manager.loadProject(quote_uri(project_file.get_uri()))
     return True
Beispiel #16
0
 def _sourceIsUsed(self, uri):
     """Check if a given URI is present in the timeline"""
     layers = self.app.current.timeline.get_layers()
     for layer in layers:
         for tlobj in layer.get_objects():
             tlobj_uri = quote_uri(tlobj.get_uri())
             if tlobj_uri == uri:
                 return True
     return False
Beispiel #17
0
 def _projectLoadedCb(self, formatter, timeline):
     self.debug("Project Loaded")
     for uri in self.formatter.get_sources():
         self._medialib_awaiting_discovery.append(quote_uri(uri))
     self.current.medialibrary.addUris(self._medialib_awaiting_discovery)
     if self._medialib_awaiting_discovery:
         self.current.medialibrary.connect("source-added", self._sourceAddedCb)
     else:
         self.emit("new-project-loaded", self.current)
         self.time_loaded = time()
Beispiel #18
0
 def getInfoFromUri(self, uri):
     """
     Get the source corresponding to C{uri}.
     """
     # Make sure the URI is properly quoted, as other modules calling this
     # method do not necessarily provide URIs encoded in the same way.
     uri = quote_uri(uri)
     info = self._sources.get(uri)
     if info is None:
         raise MediaLibraryError("URI not in the medialibrary", uri)
     return info
Beispiel #19
0
 def __init__(self, media_filenames, add_to_timeline=False, debug=False):
     GuiPitivi.__init__(self, debug)
     # load the passed filenames, optionally adding them to the timeline
     # (useful during development)
     self.projectManager.newBlankProject(emission=False)
     uris = [quote_uri(os.path.abspath(media_filename))
             for media_filename in media_filenames]
     lib = self.current_project.medialibrary
     lib.connect("source-added", self._sourceAddedCb, uris, add_to_timeline)
     lib.connect("discovery-error", self._discoveryErrorCb, uris)
     lib.addUris(uris)
Beispiel #20
0
    def _setScenarioFile(self, uri):
        if 'PITIVI_SCENARIO_FILE' in os.environ:
            uri = quote_uri(os.environ['PITIVI_SCENARIO_FILE'])
        else:
            cache_dir = get_dir(os.path.join(xdg_cache_home(), "scenarios"))
            scenario_name = str(time.strftime("%Y%m%d-%H%M%S"))
            project_path = None
            if uri:
                project_path = path_from_uri(uri)
                scenario_name += os.path.splitext(project_path.replace(os.sep, "_"))[0]

            uri = os.path.join(cache_dir, scenario_name + ".scenario")
            uri = quote_uri(uri)

        self._scenario_file = open(path_from_uri(uri), "w")

        if project_path:
            f = open(project_path)
            content = f.read()
            self.write_action("load-project",
                              {"serialized-content":
                               "%s" % content.replace("\n", "")})
            f.close()
Beispiel #21
0
    def _addAsset(self, asset):
        info = asset.get_info()

        # The code below tries to read existing thumbnails from the freedesktop
        # thumbnails directory (~/.thumbnails). The filenames are simply
        # the file URI hashed with md5, so we can retrieve them easily.
        video_streams = [i for i in info.get_stream_list() if isinstance(i, DiscovererVideoInfo)]
        if len(video_streams) > 0:
            # From the freedesktop spec: "if the environment variable
            # $XDG_CACHE_HOME is set and not blank then the directory
            # $XDG_CACHE_HOME/thumbnails will be used, otherwise
            # $HOME/.cache/thumbnails will be used."
            # Older version of the spec also mentioned $HOME/.thumbnails
            thumbnail_hash = md5(quote_uri(info.get_uri())).hexdigest()
            try:
                thumb_dir = os.environ['XDG_CACHE_HOME']
                thumbnail, thumbnail_large = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            except KeyError:
                thumbnail, thumbnail_large = (None, None)
            if thumbnail is None:
                thumb_dir = os.path.expanduser("~/.cache/thumbnails/")
                thumbnail, thumbnail_large = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            if thumbnail is None:
                thumb_dir = os.path.expanduser("~/.thumbnails/")
                thumbnail, thumbnail_large = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            if thumbnail is None:
                thumbnail = self.videofilepixbuf
                # TODO gst discoverer should create missing thumbnails.
                thumbnail_large = thumbnail
        else:
            thumbnail = self.audiofilepixbuf
            thumbnail_large = self.audiofilepixbuf

        if info.get_duration() == Gst.CLOCK_TIME_NONE:
            duration = ''
        else:
            duration = beautify_length(info.get_duration())

        name = info_name(info)

        self.pending_rows.append((thumbnail,
                                  thumbnail_large,
                                  beautify_info(info),
                                  asset,
                                  info.get_uri(),
                                  duration,
                                  name))
        if len(self.pending_rows) > 50:
            self.flush_pending_rows()
Beispiel #22
0
    def _addAsset(self, asset):
        info = asset.get_info()

        # The code below tries to read existing thumbnails from the freedesktop
        # thumbnails directory (~/.thumbnails). The filenames are simply
        # the file URI hashed with md5, so we can retrieve them easily.
        video_streams = [i for i in info.get_stream_list() if isinstance(i, DiscovererVideoInfo)]
        if len(video_streams) > 0:
            # From the freedesktop spec: "if the environment variable
            # $XDG_CACHE_HOME is set and not blank then the directory
            # $XDG_CACHE_HOME/thumbnails will be used, otherwise
            # $HOME/.cache/thumbnails will be used."
            # Older version of the spec also mentioned $HOME/.thumbnails
            thumbnail_hash = md5(quote_uri(info.get_uri())).hexdigest()
            try:
                thumb_dir = os.environ['XDG_CACHE_HOME']
                thumbnail, thumbnail_large = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            except KeyError:
                thumbnail, thumbnail_large = (None, None)
            if thumbnail is None:
                thumb_dir = os.path.expanduser("~/.cache/thumbnails/")
                thumbnail, thumbnail_large = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            if thumbnail is None:
                thumb_dir = os.path.expanduser("~/.thumbnails/")
                thumbnail, thumbnail_large = self._getThumbnailInDir(thumb_dir, thumbnail_hash)
            if thumbnail is None:
                thumbnail = self.videofilepixbuf
                # TODO gst discoverer should create missing thumbnails.
                thumbnail_large = thumbnail
        else:
            thumbnail = self.audiofilepixbuf
            thumbnail_large = self.audiofilepixbuf

        if info.get_duration() == Gst.CLOCK_TIME_NONE:
            duration = ''
        else:
            duration = beautify_length(info.get_duration())

        name = info_name(info)

        self.pending_rows.append((thumbnail,
                                  thumbnail_large,
                                  beautify_info(info),
                                  asset,
                                  info.get_uri(),
                                  duration,
                                  name))
        if len(self.pending_rows) > 50:
            self.flush_pending_rows()
Beispiel #23
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)
Beispiel #24
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)
Beispiel #25
0
    def __init__(self, bElement, 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.ScrollActor.__init__(self)
        Loggable.__init__(self)
        PreviewGenerator.__init__(self, GES.TrackType.VIDEO)

        # Variables related to the timeline objects
        self.timeline = timeline
        self.bElement = bElement
        self.uri = quote_uri(bElement.props.uri)  # Guard against malformed URIs
        self.duration = bElement.props.duration

        # Variables related to thumbnailing
        self.wishlist = []
        self._callback_id = None
        self._thumb_cb_id = None
        self._allAnimated = False
        self._running = False
        # We should have one thumbnail per thumb_period.
        # TODO: get this from the user settings
        self.thumb_period = long(0.5 * Gst.SECOND)
        self.thumb_margin = BORDER_WIDTH
        self.thumb_height = EXPANDED_SIZE - 2 * self.thumb_margin
        self.thumb_width = None  # will be set by self._setupPipeline()

        # Maps (quantized) times to Thumbnail objects
        self.thumbs = {}
        self.thumb_cache = get_cache_for_uri(self.uri)

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

        # Connect signals and fire things up
        self.timeline.connect("scrolled", self._scrollCb)
        self.bElement.connect("notify::duration", self._durationChangedCb)
        self.bElement.connect("notify::in-point", self._inpointChangedCb)
        self.bElement.connect("notify::start", self._startChangedCb)

        self.pipeline = None
        self.becomeControlled()
Beispiel #26
0
    def __init__(self, ges_elem, max_cpu_usage):
        Previewer.__init__(self, GES.TrackType.VIDEO, max_cpu_usage)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.ges_elem = ges_elem

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

        self.__start_id = 0
        self.__preroll_timeout_id = 0
        self._thumb_cb_id = 0

        # The thumbs to be generated.
        self.queue = []
        # The position for which a thumbnail is currently being generated.
        self.position = -1
        # The positions for which we failed to get a pixbuf.
        self.failures = set()
        self._thumb_cb_id = None

        self.thumbs = {}
        self.thumb_height = THUMB_HEIGHT
        self.thumb_width = 0

        self.__image_pixbuf = None
        if not isinstance(ges_elem, GES.ImageSource):
            self.thumb_cache = ThumbnailCache.get(self.uri)
            self._ensure_proxy_thumbnails_cache()
            self.thumb_width, unused_height = self.thumb_cache.image_size
        self.pipeline = None
        self.gdkpixbufsink = None

        self.cpu_usage_tracker = CPUUsageTracker()
        # Initial delay before generating the next thumbnail, in millis.
        self.interval = 500

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

        self.become_controlled()

        self.connect("notify::height-request", self._height_changed_cb)
Beispiel #27
0
    def __init__(self, bElement, timeline):
        """
        @param bElement : the backend GES.TrackElement
        @param track : the track to which the bElement belongs
        @param timeline : the containing graphic timeline.
        """
        Clutter.ScrollActor.__init__(self)
        PreviewGenerator.__init__(self, GES.TrackType.VIDEO)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        # Variables related to the timeline objects
        self.timeline = timeline
        self.bElement = bElement
        # Guard against malformed URIs
        self.uri = quote_uri(bElement.props.uri)
        self.duration = bElement.props.duration

        # Variables related to thumbnailing
        self.wishlist = []
        self._thumb_cb_id = None
        self._allAnimated = False
        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 = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX
        self.thumb_width = None  # will be set by self._setupPipeline()

        # Maps (quantized) times to Thumbnail objects
        self.thumbs = {}
        self.thumb_cache = get_cache_for_uri(self.uri)

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

        # Connect signals and fire things up
        self.timeline.connect("scrolled", self._scrollCb)
        self.bElement.connect("notify::duration", self._durationChangedCb)
        self.bElement.connect("notify::in-point", self._inpointChangedCb)
        self.bElement.connect("notify::start", self._startChangedCb)

        self.pipeline = None
        self.becomeControlled()
Beispiel #28
0
    def __init__(self, ges_elem):
        """
        @param ges_elem : the backend GES.TrackElement
        @param track : the track to which the ges_elem belongs
        """
        Previewer.__init__(self, GES.TrackType.VIDEO)
        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)

        # 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

        # Maps (quantized) times to Thumbnail objects
        self.thumbs = {}
        self.thumb_cache = getThumbnailCache(self.uri)
        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._inpointChangedCb)

        self.pipeline = None
        self.gdkpixbufsink = None
        self.__last_rectangle = Gdk.Rectangle()
        self.becomeControlled()

        self.connect("notify::height-request", self._heightChangedCb)
Beispiel #29
0
    def __init__(self, bElement):
        """
        @param bElement : the backend GES.TrackElement
        @param track : the track to which the bElement belongs
        """
        super(VideoPreviewer, self).__init__()
        PreviewGenerator.__init__(self, GES.TrackType.VIDEO)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        # Variables related to the timeline objects
        self.timeline = bElement.get_parent().get_timeline().ui
        self.bElement = bElement
        # Guard against malformed URIs
        self.uri = quote_uri(bElement.props.uri)

        # Variables related to thumbnailing
        self.wishlist = []
        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 = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX

        # Maps (quantized) times to Thumbnail objects
        self.thumbs = {}
        self.thumb_cache = get_cache_for_uri(self.uri)
        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.bElement.connect("notify::in-point", self._inpointChangedCb)

        self.pipeline = None
        self.__last_rectangle = Gdk.Rectangle()
        self.becomeControlled()

        self.connect("notify::height-request", self._heightChangedCb)
Beispiel #30
0
    def removeUri(self, uri):
        """
        Remove the info for c{uri} from the source list.
        """
        # In theory we don't need quote_uri here, but since removeUri is public,
        # we can never be too sure.
        uri = quote_uri(uri)
        try:
            info = self._sources.pop(uri)
        except KeyError:
            raise MediaLibraryError("URI not in the medialibrary", uri)
        try:
            self._ordered_sources.remove(info)
        except ValueError:
            # this can only happen if discoverer hasn't finished scanning the
            # source, so info must be None
            assert info is None

        self.debug("Removing %s", uri)
        self.emit("source-removed", uri, info)
Beispiel #31
0
    def __init__(self, ges_elem, max_cpu_usage):
        Previewer.__init__(self, GES.TrackType.VIDEO, max_cpu_usage)
        Zoomable.__init__(self)
        Loggable.__init__(self)

        self.ges_elem = ges_elem

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

        self.__start_id = 0

        self.__image_pixbuf = None

        self.thumbs = {}
        self.thumb_height = THUMB_HEIGHT
        self.thumb_width = 0

        self.ges_elem.connect("notify::duration", self._duration_changed_cb)

        self.become_controlled()

        self.connect("notify::height-request", self._height_changed_cb)
Beispiel #32
0
    def _setScenarioFile(self, uri):
        if uri:
            project_path = path_from_uri(uri)
        else:
            # New project.
            project_path = None
        if 'PITIVI_SCENARIO_FILE' in os.environ:
            scenario_path = os.environ['PITIVI_SCENARIO_FILE']
        else:
            cache_dir = get_dir(os.path.join(xdg_cache_home(), "scenarios"))
            scenario_name = str(time.strftime("%Y%m%d-%H%M%S"))
            if project_path:
                scenario_name += os.path.splitext(project_path.replace(os.sep, "_"))[0]
            scenario_path = os.path.join(cache_dir, scenario_name + ".scenario")

        scenario_path = path_from_uri(quote_uri(scenario_path))
        self._scenario_file = open(scenario_path, "w")

        if project_path and not project_path.endswith(".scenario"):
            # It's an xges file probably.
            with open(project_path) as project:
                content = project.read().replace("\n", "")
                self.write_action("load-project",
                                  serialized_content=content)
Beispiel #33
0
    def saveProject(self, project, uri=None, overwrite=False, formatter=None, backup=False):
        """
        Save the L{Project} to the given location.

        If specified, use the given formatter.

        @type project: L{Project}
        @param project: The L{Project} to save.
        @type uri: L{str}
        @param uri: The absolute URI of the location to store the project to.
        @param overwrite: Whether to overwrite existing location.
        @type overwrite: C{bool}
        @type formatter: L{Formatter}
        @param formatter: The L{Formatter} to use to store the project if specified.
        If it is not specified, then it will be saved at its original format.
        @param backup: Whether the requested save operation is for a backup
        @type backup: C{bool}

        @see: L{Formatter.saveProject}
        """
        if formatter is None:
            formatter = GES.PitiviFormatter()
        if backup:
            if project.uri and self.current.uri is not None:
                # Ignore whatever URI that is passed on to us. It's a trap.
                uri = self._makeBackupURI(project.uri)
            else:
                # Do not try to save backup files for blank projects.
                # It is possible that self.current.uri == None when the backup
                # timer sent us an old instance of the (now closed) project.
                return
        elif uri is None:
            # This allows calling saveProject without specifying the target URI
            uri = project.uri
        else:
            # Ensure the URI we are given is properly encoded, or GIO will fail
            uri = quote_uri(uri)

            # The following needs to happen before we change project.uri:
            if not isWritable(path_from_uri(uri)):
                # TODO: this will not be needed when GTK+ bug #601451 is fixed
                self.emit("save-project-failed", uri,
                        _("You do not have permissions to write to this folder."))
                return

            # Update the project instance's uri for the "Save as" scenario.
            # Otherwise, subsequent saves will be to the old uri.
            if not backup:
                project.uri = uri

        if uri is None or not formatter.can_save_uri(uri):
            self.emit("save-project-failed", uri,
                    _("Cannot save with this file format."))
            return

        if overwrite or not os.path.exists(path_from_uri(uri)):
            formatter.set_sources(project.medialibrary.getSources())
            saved = formatter.save_to_uri(project.timeline, uri)
            if saved:
                if not backup:
                    # Do not emit the signal when autosaving a backup file
                    self.emit("project-saved", project, uri)
                    self.debug('Saved project "%s"' % uri)
                else:
                    self.debug('Saved backup "%s"' % uri)
            return saved
Beispiel #34
0
 def _ensure_proxy_thumbnails_cache(self):
     """Ensures that both the target asset and the proxy assets have caches."""
     uri = quote_uri(self.ges_elem.props.uri)
     if self.uri != uri:
         self.thumb_cache.copy(uri)
Beispiel #35
0
 def _ensure_proxy_thumbnails_cache(self):
     """Ensures that both the target asset and the proxy assets have caches."""
     uri = quote_uri(self.ges_elem.props.uri)
     if self.uri != uri:
         self.thumb_cache.copy(uri)
Beispiel #36
0
    def _addAsset(self, asset):
        # 128 is the normal size for thumbnails, but for *icons* it looks
        # insane
        LARGE_SIZE = 96
        info = asset.get_info()

        # The code below tries to read existing thumbnails from the freedesktop
        # thumbnails directory (~/.thumbnails). The filenames are simply
        # the file URI hashed with md5, so we can retrieve them easily.
        video_streams = [
            i for i in info.get_stream_list()
            if isinstance(i, DiscovererVideoInfo)
        ]
        if len(video_streams) > 0:
            # From the freedesktop spec: "if the environment variable
            # $XDG_CACHE_HOME is set and not blank then the directory
            # $XDG_CACHE_HOME/thumbnails will be used, otherwise
            # $HOME/.cache/thumbnails will be used."
            # Older version of the spec also mentioned $HOME/.thumbnails
            quoted_uri = quote_uri(info.get_uri())
            thumbnail_hash = md5(quoted_uri.encode()).hexdigest()
            try:
                thumb_dir = os.environ['XDG_CACHE_HOME']
                thumb_64, thumb_128 = self._getThumbnailInDir(
                    thumb_dir, thumbnail_hash)
            except KeyError:
                thumb_64, thumb_128 = (None, None)
            if thumb_64 is None:
                thumb_dir = os.path.expanduser("~/.cache/thumbnails/")
                thumb_64, thumb_128 = self._getThumbnailInDir(
                    thumb_dir, thumbnail_hash)
            if thumb_64 is None:
                thumb_dir = os.path.expanduser("~/.thumbnails/")
                thumb_64, thumb_128 = self._getThumbnailInDir(
                    thumb_dir, thumbnail_hash)
            if thumb_64 is None:
                if asset.is_image():
                    thumb_64 = self._getIcon("image-x-generic")
                    thumb_128 = self._getIcon("image-x-generic", None,
                                              LARGE_SIZE)
                else:
                    thumb_64 = self._getIcon("video-x-generic")
                    thumb_128 = self._getIcon("video-x-generic", None,
                                              LARGE_SIZE)
                # TODO ideally gst discoverer should create missing thumbnails.
                self.log("Missing a thumbnail for %s, queuing",
                         path_from_uri(quoted_uri))
                self._missing_thumbs.append(quoted_uri)
        else:
            thumb_64 = self._getIcon("audio-x-generic")
            thumb_128 = self._getIcon("audio-x-generic", None, LARGE_SIZE)

        if info.get_duration() == Gst.CLOCK_TIME_NONE:
            duration = ''
        else:
            duration = beautify_length(info.get_duration())

        name = info_name(info)

        self.pending_rows.append((thumb_64, thumb_128, beautify_info(info),
                                  asset, info.get_uri(), duration, name))
        if len(self.pending_rows) > 50:
            self.flush_pending_rows()
Beispiel #37
0
 def __init__(self, project_filename, debug=False):
     GuiPitivi.__init__(self, debug)
     if not os.path.exists(project_filename):
         self.error("Project file does not exist: %s" % project_filename)
         sys.exit(1)
     self.projectManager.loadProject(quote_uri(os.path.abspath(project_filename)))
Beispiel #38
0
 def _loadProject(self, project_filename):
     self.projectManager.loadProject(quote_uri(os.path.abspath(project_filename)))