[pitivi] render: Rework the way the file to render to is chosen
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] render: Rework the way the file to render to is chosen
- Date: Tue, 19 Jan 2021 21:06:48 +0000 (UTC)
commit 56caf8b735c6c4dcfb686cbfff833361a1452ab7
Author: Thibault Saunier <tsaunier igalia com>
Date: Fri Jan 8 12:38:58 2021 -0300
render: Rework the way the file to render to is chosen
Instead of having a atypical way of selecting on one side the directory
and on the other side the filename, use a standard GtkFileChooser dialog
to select the file where to render, allowing the user to also manually
specify the file path in a text entry.
data/ui/renderingdialog.ui | 89 ++++++++++++++++---------------------
pitivi/medialibrary.py | 36 +--------------
pitivi/render.py | 106 +++++++++++++++++++++++++++------------------
pitivi/utils/misc.py | 77 ++++++++++++++++++++++++++++++++
pitivi/utils/ui.py | 34 +++++++++++++++
tests/test_medialibrary.py | 15 -------
tests/test_render.py | 12 ++---
tests/test_utils.py | 16 +++++++
8 files changed, 236 insertions(+), 149 deletions(-)
---
diff --git a/data/ui/renderingdialog.ui b/data/ui/renderingdialog.ui
index 5bbdc5d4c..c94a5e860 100644
--- a/data/ui/renderingdialog.ui
+++ b/data/ui/renderingdialog.ui
@@ -219,57 +219,6 @@
<property name="top_attach">0</property>
</packing>
</child>
- <child>
- <object class="GtkFileChooserButton" id="filebutton">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="action">select-folder</property>
- <signal name="current-folder-changed" handler="_current_folder_changed_cb" swapped="no"/>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="valign">center</property>
- <property name="label" translatable="yes">Folder:</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="fileentry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="activates_default">True</property>
- <signal name="changed" handler="_filename_changed_cb" swapped="no"/>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label5">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="valign">center</property>
- <property name="label" translatable="yes">File name:</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">4</property>
- </packing>
- </child>
<child>
<object class="GtkExpander" id="advanced_expander">
<property name="name">Advanced</property>
@@ -838,6 +787,44 @@ This option is a good trade-off between quality of the rendered video and stabil
<property name="top_attach">2</property>
</packing>
</child>
+ <child>
+ <object class="GtkButton" id="filebutton">
+ <property name="label" translatable="yes">Select file</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="_select_file_clicked_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">File path:</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="fileentry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates-default">True</property>
+ <signal name="changed" handler="_fileentry_changed_cb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
<child>
<placeholder/>
</child>
diff --git a/pitivi/medialibrary.py b/pitivi/medialibrary.py
index 0e307aa63..4f6b1a6c0 100644
--- a/pitivi/medialibrary.py
+++ b/pitivi/medialibrary.py
@@ -53,10 +53,10 @@ from pitivi.utils.misc import quote_uri
from pitivi.utils.misc import show_user_manual
from pitivi.utils.proxy import get_proxy_target
from pitivi.utils.proxy import ProxyingStrategy
-from pitivi.utils.proxy import ProxyManager
from pitivi.utils.ui import beautify_asset
from pitivi.utils.ui import beautify_eta
from pitivi.utils.ui import FILE_TARGET_ENTRY
+from pitivi.utils.ui import filter_unsupported_media_files
from pitivi.utils.ui import fix_infobar
from pitivi.utils.ui import info_name
from pitivi.utils.ui import LARGE_THUMB_WIDTH
@@ -104,28 +104,6 @@ class AssetStoreItem(GObject.GObject):
self.thumb_decorator = thumb_decorator
-# This whitelist is made from personal knowledge of file extensions in the wild,
-# from gst-inspect |grep demux,
-# http://en.wikipedia.org/wiki/Comparison_of_container_formats and
-# http://en.wikipedia.org/wiki/List_of_file_formats#Video
-# ...and looking at the contents of /usr/share/mime
-SUPPORTED_FILE_FORMATS = {
- "video": ("3gpp", "3gpp2", "dv", "mp2t", "mp2t", "mp4", "mpeg", "ogg",
- "quicktime", "webm", "x-flv", "x-matroska", "x-mng", "x-ms-asf",
- "x-ms-wmp", "x-ms-wmv", "x-msvideo", "x-ogm+ogg", "x-theora+ogg"),
- "application": ("mxf",),
- "audio": ("aac", "ac3", "basic", "flac", "mp2", "mp4", "mpeg", "ogg",
- "opus", "webm", "x-adpcm", "x-aifc", "x-aiff", "x-aiffc",
- "x-ape", "x-flac+ogg", "x-m4b", "x-matroska", "x-ms-asx",
- "x-ms-wma", "x-speex", "x-speex+ogg", "x-vorbis+ogg", "x-wav"),
- "image": ("jp2", "jpeg", "png", "svg+xml")}
-
-SUPPORTED_MIMETYPES = []
-for category, mime_types in SUPPORTED_FILE_FORMATS.items():
- for mime in mime_types:
- SUPPORTED_MIMETYPES.append(category + "/" + mime)
-
-
class OptimizeOption(IntEnum):
UNSUPPORTED_ASSETS = 0
ALL = 1
@@ -760,16 +738,6 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
project.connect("proxying-error", self._proxying_error_cb)
project.connect("settings-set-from-imported-asset",
self.__project_settings_set_from_imported_asset_cb)
- def _filter_unsupported(self, filter_info):
- """Returns whether the specified item should be displayed."""
- if filter_info.mime_type not in SUPPORTED_MIMETYPES:
- return False
-
- if ProxyManager.is_proxy_asset(filter_info.uri):
- return False
-
- return True
-
def show_import_assets_dialog(self):
"""Pops up the "Import Sources" dialog box."""
dialog = Gtk.FileChooserDialog()
@@ -794,7 +762,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
file_filter = Gtk.FileFilter()
file_filter.set_name(_("Supported file formats"))
file_filter.add_custom(Gtk.FileFilterFlags.URI | Gtk.FileFilterFlags.MIME_TYPE,
- self._filter_unsupported)
+ filter_unsupported_media_files)
for formatter in GES.list_assets(GES.Formatter):
for extension in formatter.get_meta("extension").split(","):
if not extension:
diff --git a/pitivi/render.py b/pitivi/render.py
index 7d090890c..6772babe2 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -34,6 +34,7 @@ from pitivi import configure
from pitivi.check import MISSING_SOFT_DEPS
from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import cmp
+from pitivi.utils.misc import is_pathname_valid
from pitivi.utils.misc import path_from_uri
from pitivi.utils.misc import show_user_manual
from pitivi.utils.ripple_update_group import RippleUpdateGroup
@@ -41,6 +42,7 @@ from pitivi.utils.ui import AUDIO_CHANNELS
from pitivi.utils.ui import AUDIO_RATES
from pitivi.utils.ui import beautify_eta
from pitivi.utils.ui import create_frame_rates_model
+from pitivi.utils.ui import filter_unsupported_media_files
from pitivi.utils.ui import get_combo_value
from pitivi.utils.ui import set_combo_value
from pitivi.utils.widgets import GstElementSettingsDialog
@@ -814,17 +816,11 @@ class RenderDialog(Loggable):
self._create_ui()
# Directory and Filename
- self.filebutton.set_current_folder(self.app.settings.lastExportFolder)
if not self.project.name:
self._update_filename(_("Untitled"))
else:
self._update_filename(self.project.name)
- # Add a shortcut for the project folder (if saved)
- if self.project.uri:
- shortcut = os.path.dirname(self.project.uri)
- self.filebutton.add_shortcut_folder_uri(shortcut)
-
self._setting_encoding_profile = False
# We store these so that when the user tries various container formats,
@@ -1133,35 +1129,30 @@ class RenderDialog(Loggable):
def _check_filename(self):
"""Displays a warning if the file path already exists."""
- path = self.filebutton.get_current_folder()
- if not path:
- # This happens when the window is initialized.
- return
-
- filename = self.fileentry.get_text()
-
- # Characters that cause pipeline failure.
- blacklist = ["/"]
- invalid_chars = "".join([ch for ch in blacklist if ch in filename])
-
- warning_icon = "dialog-warning"
- self._is_filename_valid = True
- if not filename:
+ filepath = self.fileentry.get_text()
+ if not filepath:
tooltip_text = _("A file name is required.")
self._is_filename_valid = False
- elif os.path.exists(os.path.join(path, filename)):
- tooltip_text = _("This file already exists.\n"
- "If you don't want to overwrite it, choose a "
- "different file name or folder.")
- elif invalid_chars:
- tooltip_text = _("Remove invalid characters from the filename: %s") % invalid_chars
- self._is_filename_valid = False
else:
- warning_icon = None
- tooltip_text = None
+ filepath = os.path.realpath(filepath)
+ if os.path.isdir(filepath):
+ tooltip_text = _("A file name is required.")
+ self._is_filename_valid = False
+ elif os.path.exists(filepath):
+ tooltip_text = _("This file already exists.\n"
+ "If you don't want to overwrite it, choose a "
+ "different file name or folder.")
+ self._is_filename_valid = True
+ elif not is_pathname_valid(filepath):
+ tooltip_text = _("Invalid file path")
+ self._is_filename_valid = False
+ else:
+ tooltip_text = None
+ self._is_filename_valid = True
- self.fileentry.set_icon_from_icon_name(1, warning_icon)
- self.fileentry.set_icon_tooltip_text(1, tooltip_text)
+ warning_icon = "dialog-warning" if tooltip_text else None
+ self.fileentry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, warning_icon)
+ self.fileentry.set_icon_tooltip_text(Gtk.EntryIconPosition.SECONDARY, tooltip_text)
self.__update_render_button_sensitivity()
def _get_filesize_estimate(self):
@@ -1199,7 +1190,8 @@ class RenderDialog(Loggable):
name = "%s%s%s" % (basename, os.path.extsep, extension)
else:
name = basename
- self.fileentry.set_text(name)
+
+ self.fileentry.set_text(os.path.join(self.app.settings.lastExportFolder, name))
def _update_valid_restriction_values(self, caps, combo, caps_template,
model, combo_value,
@@ -1489,12 +1481,43 @@ class RenderDialog(Loggable):
getattr(self.project, media_type + "_profile").set_format(caps)
self.dialog.window.destroy()
+ def _select_file_clicked_cb(self, unused_button):
+ chooser = Gtk.FileChooserNative.new(
+ _("Select file path to render"),
+ self.window,
+ Gtk.FileChooserAction.SAVE,
+ None, None)
+
+ file_filter = Gtk.FileFilter()
+ file_filter.set_name(_("Supported file formats"))
+ file_filter.add_custom(Gtk.FileFilterFlags.URI | Gtk.FileFilterFlags.MIME_TYPE,
+ filter_unsupported_media_files)
+ chooser.add_filter(file_filter)
+ chooser.set_current_folder(self.app.settings.lastExportFolder)
+ # Add a shortcut for the project folder (if saved)
+ if self.project.uri:
+ shortcut = os.path.dirname(self.project.uri)
+ chooser.add_shortcut_folder_uri(shortcut)
+
+ response = chooser.run()
+ if response == Gtk.ResponseType.DELETE_EVENT:
+ # This happens because Gtk.FileChooserNative is confused because we
+ # added a filter but since it's ignored it complains there is none.
+ # Try again without the filter.
+ chooser.remove_filter(file_filter)
+ response = chooser.run()
+
+ if response == Gtk.ResponseType.ACCEPT:
+ self.app.settings.lastExportFolder = chooser.get_current_folder()
+ self.fileentry.set_text(os.path.join(chooser.get_filename()))
+
def _render_button_clicked_cb(self, unused_button):
"""Starts the rendering process."""
self.__replace_proxies()
self.__unset_effect_preview_props()
- self.outfile = os.path.join(self.filebutton.get_uri(),
- self.fileentry.get_text())
+ filename = os.path.realpath(self.fileentry.get_text())
+ self.outfile = Gst.filename_to_uri(filename)
+ self.app.settings.lastExportFolder = os.path.dirname(filename)
self.progress = RenderingProgressDialog(self.app, self)
# Hide the rendering settings dialog while rendering
self.window.hide()
@@ -1513,7 +1536,6 @@ class RenderDialog(Loggable):
self.project.pipeline.connect("position", self._update_position_cb)
# Force writing the config now, or the path will be reset
# if the user opens the rendering dialog again
- self.app.settings.lastExportFolder = self.filebutton.get_current_folder()
self.app.settings.store_settings()
def _close_button_clicked_cb(self, unused_button):
@@ -1528,10 +1550,7 @@ class RenderDialog(Loggable):
def _container_context_help_clicked_cb(self, unused_button):
show_user_manual("codecscontainers")
- def _current_folder_changed_cb(self, *unused_args):
- self._check_filename()
-
- def _filename_changed_cb(self, *unused_args):
+ def _fileentry_changed_cb(self, unused_entry):
self._check_filename()
# Periodic (timer) callbacks
@@ -1539,6 +1558,7 @@ class RenderDialog(Loggable):
if self._rendering_is_paused:
# Do nothing until we resume rendering
return True
+
if self._is_rendering:
if self.current_position:
timediff = time.time() - self._time_started - self._time_spent_paused
@@ -1549,10 +1569,10 @@ class RenderDialog(Loggable):
if estimate:
self.progress.update_progressbar_eta(estimate)
return True
- else:
- self._time_estimate_timer = None
- self.debug("Stopping the ETA timer")
- return False
+
+ self._time_estimate_timer = None
+ self.debug("Stopping the ETA timer")
+ return False
def _update_filesize_estimate_cb(self):
if self._rendering_is_paused:
diff --git a/pitivi/utils/misc.py b/pitivi/utils/misc.py
index 9897c2dd4..18c874a3d 100644
--- a/pitivi/utils/misc.py
+++ b/pitivi/utils/misc.py
@@ -15,8 +15,10 @@
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+import errno
import os
import subprocess
+import sys
import threading
import time
from gettext import gettext as _
@@ -480,3 +482,78 @@ def asset_get_duration(asset):
def cmp(item1, item2):
return (item1 > item2) - (item1 < item2)
+
+
+# Windows-specific error code indicating an invalid pathname.
+# See Also
+# ----------
+# https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
+# Official listing of all such codes.
+ERROR_INVALID_NAME = 123
+
+
+def is_pathname_valid(pathname: str) -> bool:
+ """`True` if the passed pathname is a valid pathname for the current OS `False` otherwise."""
+ # If this pathname is either not a string or is but is empty, this pathname
+ # is invalid.
+ try:
+ if not isinstance(pathname, str) or not pathname:
+ return False
+
+ # Strip this pathname's Windows-specific drive specifier (e.g., `C:\`)
+ # if any. Since Windows prohibits path components from containing `:`
+ # characters, failing to strip this `:`-suffixed prefix would
+ # erroneously invalidate all valid absolute Windows pathnames.
+ _, pathname = os.path.splitdrive(pathname)
+
+ # Directory guaranteed to exist. If the current OS is Windows, this is
+ # the drive to which Windows was installed (e.g., the "%HOMEDRIVE%"
+ # environment variable); else, the typical root directory.
+ root_dirname = os.environ.get('HOMEDRIVE', 'C:') \
+ if sys.platform == 'win32' else os.path.sep
+ assert os.path.isdir(root_dirname) # ...Murphy and her ironclad Law
+
+ # Append a path separator to this directory if needed.
+ root_dirname = root_dirname.rstrip(os.path.sep) + os.path.sep
+
+ # Test whether each path component split from this pathname is valid or
+ # not, ignoring non-existent and non-readable path components.
+ for pathname_part in pathname.split(os.path.sep):
+ try:
+ os.lstat(root_dirname + pathname_part)
+ # If an OS-specific exception is raised, its error code
+ # indicates whether this pathname is valid or not. Unless this
+ # is the case, this exception implies an ignorable kernel or
+ # filesystem complaint (e.g., path not found or inaccessible).
+ #
+ # Only the following exceptions indicate invalid pathnames:
+ #
+ # * Instances of the Windows-specific "WindowsError" class
+ # defining the "winerror" attribute whose value is
+ # "ERROR_INVALID_NAME". Under Windows, "winerror" is more
+ # fine-grained and hence useful than the generic "errno"
+ # attribute. When a too-long pathname is passed, for example,
+ # "errno" is "ENOENT" (i.e., no such file or directory) rather
+ # than "ENAMETOOLONG" (i.e., file name too long).
+ # * Instances of the cross-platform "OSError" class defining the
+ # generic "errno" attribute whose value is either:
+ # * Under most POSIX-compatible OSes, "ENAMETOOLONG".
+ # * Under some edge-case OSes (e.g., SunOS, *BSD), "ERANGE".
+ except OSError as exc:
+ if hasattr(exc, 'winerror'):
+ if exc.winerror == ERROR_INVALID_NAME:
+ return False
+ elif exc.errno in {errno.ENAMETOOLONG, errno.ERANGE}:
+ return False
+ # If a "TypeError" exception was raised, it almost certainly has the
+ # error message "embedded NUL character" indicating an invalid pathname.
+ except TypeError as exc:
+ return False
+ # If no exception was raised, all path components and hence this
+ # pathname itself are valid. (Praise be to the curmudgeonly python.)
+ else:
+ return True
+ # If any other exception was raised, this is an unrelated fatal issue
+ # (e.g., a bug). Permit this exception to unwind the call stack.
+ #
+ # Did we mention this should be shipped with Python already?
diff --git a/pitivi/utils/ui.py b/pitivi/utils/ui.py
index 10e90874e..35e472de3 100644
--- a/pitivi/utils/ui.py
+++ b/pitivi/utils/ui.py
@@ -892,3 +892,37 @@ AUDIO_RATES = create_model((str, int),
48000,
96000
)])
+
+# This whitelist is made from personal knowledge of file extensions in the wild,
+# from gst-inspect |grep demux,
+# http://en.wikipedia.org/wiki/Comparison_of_container_formats and
+# http://en.wikipedia.org/wiki/List_of_file_formats#Video
+# ...and looking at the contents of /usr/share/mime
+SUPPORTED_FILE_FORMATS = {
+ "video": ("3gpp", "3gpp2", "dv", "mp2t", "mp2t", "mp4", "mpeg", "ogg",
+ "quicktime", "webm", "x-flv", "x-matroska", "x-mng", "x-ms-asf",
+ "x-ms-wmp", "x-ms-wmv", "x-msvideo", "x-ogm+ogg", "x-theora+ogg"),
+ "application": ("mxf",),
+ "audio": ("aac", "ac3", "basic", "flac", "mp2", "mp4", "mpeg", "ogg",
+ "opus", "webm", "x-adpcm", "x-aifc", "x-aiff", "x-aiffc",
+ "x-ape", "x-flac+ogg", "x-m4b", "x-matroska", "x-ms-asx",
+ "x-ms-wma", "x-speex", "x-speex+ogg", "x-vorbis+ogg", "x-wav"),
+ "image": ("jp2", "jpeg", "png", "svg+xml")}
+
+SUPPORTED_MIMETYPES = []
+for category, mime_types in SUPPORTED_FILE_FORMATS.items():
+ for mime in mime_types:
+ SUPPORTED_MIMETYPES.append(category + "/" + mime)
+
+
+def filter_unsupported_media_files(filter_info):
+ """Returns whether the specified item should be displayed."""
+ from pitivi.utils.proxy import ProxyManager
+
+ if filter_info.mime_type not in SUPPORTED_MIMETYPES:
+ return False
+
+ if ProxyManager.is_proxy_asset(filter_info.uri):
+ return False
+
+ return True
diff --git a/tests/test_medialibrary.py b/tests/test_medialibrary.py
index daef7f720..f077126b3 100644
--- a/tests/test_medialibrary.py
+++ b/tests/test_medialibrary.py
@@ -192,21 +192,6 @@ class BaseTestMediaLibrary(common.TestCase):
class TestMediaLibrary(BaseTestMediaLibrary):
- def test_import_dialog_proxy_filter(self):
- mock_filter = mock.Mock()
- mock_filter.mime_type = "video/mp4"
-
- self._custom_set_up()
- mlib = self.medialibrary
-
- # Test HQ Proxies are filtered
- mock_filter.uri = "file:///home/user/Videos/video.mp4.2360382.proxy.mov"
- self.assertFalse(mlib._filter_unsupported(mock_filter))
-
- # Test Scaled Proxies are filtered
- mock_filter.uri = "file:///home/user/Videos/video.mp4.2360382.300x300.scaledproxy.mov"
- self.assertFalse(mlib._filter_unsupported(mock_filter))
-
def stop_using_proxies(self, delete_proxies=False):
sample_name = "30fps_numeroted_frames_red.mkv"
self.check_import([sample_name])
diff --git a/tests/test_render.py b/tests/test_render.py
index 47aac4dde..6dd98425a 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -321,11 +321,10 @@ class TestRender(BaseTestMediaLibrary):
from pitivi.render import RenderingProgressDialog
with tempfile.TemporaryDirectory() as temp_dir:
# Start rendering
- with mock.patch.object(dialog.filebutton, "get_uri",
- return_value=Gst.filename_to_uri(temp_dir)):
- with mock.patch.object(dialog.fileentry, "get_text", return_value="outfile"):
- with mock.patch.object(RenderingProgressDialog, "__new__"):
- dialog._render_button_clicked_cb(None)
+ with mock.patch.object(dialog.fileentry, "get_text",
+ return_value=os.path.join(temp_dir, "outfile")):
+ with mock.patch.object(RenderingProgressDialog, "__new__"):
+ dialog._render_button_clicked_cb(None)
message = dialog._pipeline.get_bus().timed_pop_filtered(
Gst.CLOCK_TIME_NONE,
@@ -335,10 +334,11 @@ class TestRender(BaseTestMediaLibrary):
dialog._pipeline, Gst.DebugGraphDetails.ALL,
"test_rendering_with_profile.dot")
- result_file = Gst.filename_to_uri(os.path.join(temp_dir, "outfile"))
struct = message.get_structure()
self.assertEqual(message.type, Gst.MessageType.EOS,
struct.to_string() if struct else message)
+
+ result_file = Gst.filename_to_uri(os.path.join(temp_dir, "outfile"))
asset = GES.UriClipAsset.request_sync(result_file)
self.assertIsNotNone(asset)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 3b73cec88..fbcaf383e 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -30,6 +30,7 @@ from pitivi.utils.misc import fixate_caps_with_default_values
from pitivi.utils.ui import beautify_last_updated_timestamp
from pitivi.utils.ui import beautify_length
from pitivi.utils.ui import create_frame_rates_model
+from pitivi.utils.ui import filter_unsupported_media_files
from pitivi.utils.ui import format_audiochannels
from pitivi.utils.ui import format_audiorate
from pitivi.utils.ui import format_framerate_value
@@ -294,3 +295,18 @@ class TestCreateFramerateModel(common.TestCase):
(130, 1)
]
self.assertListEqual([(row[1].num, row[1].denom) for row in model], sorted_frameslist)
+
+
+class TestFiltering(common.TestCase):
+
+ def test_filter_unsupported_media_files(self):
+ mock_filter_info = mock.Mock()
+ mock_filter_info.mime_type = "video/mp4"
+
+ # Test HQ Proxies are filtered
+ mock_filter_info.uri = "file:///home/user/Videos/video.mp4.2360382.proxy.mov"
+ self.assertFalse(filter_unsupported_media_files(mock_filter_info))
+
+ # Test Scaled Proxies are filtered
+ mock_filter_info.uri = "file:///home/user/Videos/video.mp4.2360382.300x300.scaledproxy.mov"
+ self.assertFalse(filter_unsupported_media_files(mock_filter_info))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]