def test_create_title(self): """Exercise creating a title clip.""" # Wait until the project creates a layer in the timeline. common.create_main_loop().run(until_empty=True) from pitivi.timeline.timeline import TimelineContainer timeline_container = TimelineContainer( self.app, editor_state=self.app.gui.editor.editor_state) timeline_container.set_project(self.project) self.app.gui.editor.timeline_ui = timeline_container clipproperties = ClipProperties(self.app) clipproperties.new_project_loaded_cb(None, self.project) self.project.pipeline.get_position = mock.Mock(return_value=0) clipproperties.create_title_clip_cb(None) ps1 = self._get_title_source_child_props() self.action_log.undo() clips = self.layer.get_clips() self.assertEqual(len(clips), 0, clips) self.action_log.redo() ps2 = self._get_title_source_child_props() self.assertListEqual(ps1, ps2)
def test_create_hard_coded(self): """Exercise creation of a color test clip.""" # Wait until the project creates a layer in the timeline. common.create_main_loop().run(until_empty=True) from pitivi.timeline.timeline import TimelineContainer timeline_container = TimelineContainer( self.app, editor_state=self.app.gui.editor.editor_state) timeline_container.set_project(self.project) self.app.gui.editor.timeline_ui = timeline_container clipproperties = ClipProperties(self.app) clipproperties.new_project_loaded_cb(None, self.project) self.project.pipeline.get_position = mock.Mock(return_value=0) clipproperties.create_color_clip_cb(None) clips = self.layer.get_clips() pattern = clips[0].get_vpattern() self.assertEqual(pattern, GES.VideoTestPattern.SOLID_COLOR) self.action_log.undo() self.assertListEqual(self.layer.get_clips(), []) self.action_log.redo() self.assertListEqual(self.layer.get_clips(), clips)
def test_use_proxy(self): # Import an asset. uris = [common.get_sample_uri("tears_of_steel.webm")] mainloop = common.create_main_loop() def loaded_cb(unused_project, unused_timeline): # The new project has been loaded, add some assets. self.project.addUris(uris) self.project.connect_after("loaded", loaded_cb) def progress_cb(unused_project, progress, unused_estimated_time): if progress == 100: # The assets have been loaded. mainloop.quit() self.project.connect_after("asset-loading-progress", progress_cb) mainloop.run() self.project.disconnect_by_func(progress_cb) self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1) # Make sure the asset is not a proxy. assets = [GES.UriClipAsset.request_sync(uri) for uri in uris] for asset in assets: self.assertIsNone(asset.get_proxy_target(), "Asset is proxy") # Use proxy instead of the asset. mainloop = common.create_main_loop() def error_cb(proxy_manager, asset, proxy, error): self.fail("Failed to create proxy: %s" % error) self.app.proxy_manager.connect("error-preparing-asset", error_cb) def proxy_ready_cb(proxy_manager, asset, proxy): mainloop.quit() self.app.proxy_manager.connect("proxy-ready", proxy_ready_cb) self.project.use_proxies_for_assets(assets) mainloop.run() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 2) # Undo proxying. self.action_log.undo() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1) # Redo proxying. self.action_log.redo() # Wait for the proxy to be signalled as ready. mainloop.run() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 2)
def test_alignment_editor(self): """Exercise aligning a clip using the alignment editor.""" # Wait until the project creates a layer in the timeline. common.create_main_loop().run(until_empty=True) from pitivi.timeline.timeline import TimelineContainer timeline_container = TimelineContainer( self.app, editor_state=self.app.gui.editor.editor_state) timeline_container.set_project(self.project) self.app.gui.editor.timeline_ui = timeline_container clipproperties = ClipProperties(self.app) clipproperties.new_project_loaded_cb(None, self.project) self.project.pipeline.get_position = mock.Mock(return_value=0) transformation_box = clipproperties.transformation_expander transformation_box._new_project_loaded_cb(self.app, self.project) timeline = timeline_container.timeline clip = self.add_clips_simple(timeline, 1)[0] timeline.selection.select([clip]) source = transformation_box.source self.assertIsNotNone(source) height = source.get_child_property("height").value width = source.get_child_property("width").value self.assertEqual(source.get_child_property("posx").value, 0) self.assertEqual(source.get_child_property("posy").value, 0) alignment_editor = transformation_box.alignment_editor event = mock.MagicMock() event.x = 0 event.y = 0 alignment_editor._motion_notify_event_cb(None, event) alignment_editor._button_release_event_cb(None, None) self.assertEqual(source.get_child_property("posx").value, -width) self.assertEqual(source.get_child_property("posy").value, -height) self.action_log.undo() self.assertEqual(source.get_child_property("posx").value, 0) self.assertEqual(source.get_child_property("posy").value, 0) self.action_log.redo() self.assertEqual(source.get_child_property("posx").value, -width) self.assertEqual(source.get_child_property("posy").value, -height)
def test_preset_persistent(self): """Checks the render preset is remembered when loading a project.""" project = self.create_simple_project() self.assertEqual(project.muxer, "webmmux") self.assertEqual(project.vencoder, "vp8enc") self.assertDictEqual(project.vcodecsettings, {}) dialog = self.create_rendering_dialog(project) self.check_quality_widget(dialog, vencoder="x264enc", vcodecsettings={ "quantizer": 21, "pass": 5 }, preset="youtube", sensitive=True, value=Quality.MEDIUM) project_manager = project.app.project_manager with tempfile.NamedTemporaryFile() as temp_file: uri = Gst.filename_to_uri(temp_file.name) project_manager.save_project(uri=uri, backup=False) app2 = common.create_pitivi() project2 = app2.project_manager.load_project(uri) timeline_container = TimelineContainer( app2, editor_state=app2.gui.editor.editor_state) timeline_container.set_project(project2) common.create_main_loop().run(until_empty=True) self.assertEqual(project2.muxer, "qtmux") self.assertEqual(project2.vencoder, "x264enc") self.assertTrue( set({ "quantizer": 21, "pass": 5 }.items()).issubset(set(project2.vcodecsettings.items()))) dialog2 = self.create_rendering_dialog(project2) self.assertTrue( set({ "quantizer": 21, "pass": 5 }.items()).issubset(set(project2.vcodecsettings.items()))) self.check_quality_widget(dialog2, vencoder="x264enc", vcodecsettings=None, preset="youtube", sensitive=True, value=Quality.MEDIUM)
def test_use_proxy(self): # Import an asset. uris = [common.get_sample_uri("tears_of_steel.webm")] mainloop = common.create_main_loop() def commit_cb(unused_action_log, stack): self.assertEqual(stack.action_group_name, "Adding assets") mainloop.quit() self.action_log.connect("commit", commit_cb) def loaded_cb(unused_project, unused_timeline): self.project.addUris(uris) self.project.connect_after("loaded", loaded_cb) mainloop.run() self.action_log.disconnect_by_func(commit_cb) self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1) # Make sure the asset is not a proxy. assets = [GES.UriClipAsset.request_sync(uri) for uri in uris] for asset in assets: self.assertIsNone(asset.get_proxy_target(), "Asset is proxy") # Use proxy instead of the asset. mainloop = common.create_main_loop() def error_cb(proxy_manager, asset, proxy, error): self.fail("Failed to create proxy: %s" % error) self.app.proxy_manager.connect("error-preparing-asset", error_cb) def proxy_ready_cb(proxy_manager, asset, proxy): uris.remove(asset.props.id) if not uris: mainloop.quit() self.app.proxy_manager.connect("proxy-ready", proxy_ready_cb) self.project.useProxiesForAssets(assets) mainloop.run() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 2) self.action_log.undo() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1) self.action_log.redo() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 2)
def test_loaded_callback(self): mainloop = common.create_main_loop() def loaded(project, timeline): # If not called, the timeout of the mainloop will fail the test. mainloop.quit() # Create a blank project and save it. project = common.create_project() project.connect("loaded", loaded) mainloop.run() # The blank project loading succeeded emitting signal "loaded". self.assertIsNotNone(project.ges_timeline) self.assertEqual(len(project.ges_timeline.get_layers()), 1) # Load the blank project and make sure "loaded" is triggered. unused, xges_path = tempfile.mkstemp() uri = "file://%s" % xges_path try: # Save so we can close it without complaints. project.save(project.ges_timeline, uri, None, overwrite=True) project2 = common.create_project() project2.connect("loaded", loaded) mainloop.run() # The blank project loading succeeded emitting signal "loaded". self.assertIsNotNone(project2.ges_timeline) self.assertEqual(len(project2.ges_timeline.get_layers()), 1) finally: os.remove(xges_path)
def test_loading_project_with_moved_assets_and_deleted_proxy(self): """Loads a project with moved asset and deleted proxy file.""" mainloop = common.create_main_loop() created_proxies = [] def proxy_ready_cb(unused_proxy_manager, asset, proxy): created_proxies.append(asset) if len(created_proxies) == 2: mainloop.quit() app = common.create_pitivi(proxying_strategy=ProxyingStrategy.ALL) app.proxy_manager.connect("proxy-ready", proxy_ready_cb) proj_uri = self.create_project_file_from_xges(r"""<ges version='0.3'> <project properties='properties;' metadatas='metadatas, name=(string)"New\ Project", author=(string)Unknown, render-scale=(double)100, format-version=(string)0.3;'> <ressources> <asset id='file:///nop/1sec_simpsons_trailer.mp4' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas, audio-codec=(string)"MPEG-4\ AAC\ audio", maximum-bitrate=(uint)130625, bitrate=(uint)130625, datetime=(datetime)2007-02-19T05:03:04Z, encoder=(string)Lavf54.6.100, container-format=(string)"ISO\ MP4/M4A", video-codec=(string)"H.264\ /\ AVC", file-size=(guint64)232417;' proxy-id='file:///nop/1sec_simpsons_trailer.mp4.232417.proxy.mov' /> <asset id='file:///nop/tears_of_steel.webm' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)2003000000;' metadatas='metadatas, container-format=(string)Matroska, language-code=(string)und, application-name=(string)Lavc56.60.100, encoder=(string)"Xiph.Org\ libVorbis\ I\ 20150105\ \(\342\233\204\342\233\204\342\233\204\342\233\204\)", encoder-version=(uint)0, audio-codec=(string)Vorbis, nominal-bitrate=(uint)80000, bitrate=(uint)80000, video-codec=(string)"VP8\ video", file-size=(guint64)223340;' proxy-id='file:///nop/tears_of_steel.webm.223340.proxy.mov'/> <asset id='file:///nop/1sec_simpsons_trailer.mp4.232417.proxy.mov' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228020833;' metadatas='metadatas, container-format=(string)Matroska, audio-codec=(string)Opus, language-code=(string)en, encoder=(string)Lavf54.6.100, bitrate=(uint)64000, video-codec=(string)"Motion\ JPEG", file-size=(guint64)4694708;' /> <asset id='file:///nop/tears_of_steel.webm.223340.proxy.mov' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)2003000000;' metadatas='metadatas, container-format=(string)Matroska, language-code=(string)und, application-name=(string)Lavc56.60.100, encoder=(string)"Xiph.Org\ libVorbis\ I\ 20150105\ \(\342\233\204\342\233\204\342\233\204\342\233\204\)", encoder-version=(uint)0, audio-codec=(string)Vorbis, nominal-bitrate=(uint)80000, bitrate=(uint)80000, video-codec=(string)"VP8\ video", file-size=(guint64)223340;' /> </ressources> </project> </ges>""") project_manager = app.project_manager medialib = MediaLibraryWidget(app) # Remove proxy with common.cloned_sample("1sec_simpsons_trailer.mp4", "tears_of_steel.webm"): def new_project_loaded_cb(*args, **kwargs): mainloop.quit() missing_uris = [] def missing_uri_cb(project_manager, project, unused_error, asset): missing_uris.append(asset.props.id) return common.get_sample_uri(os.path.basename(asset.props.id)) project_manager.connect("missing-uri", missing_uri_cb) project_manager.connect("new-project-loaded", new_project_loaded_cb) project_manager.load_project(proj_uri) mainloop.run() self.assertEqual( len(missing_uris), 1, "missing_uri_cb should be called only once, got %s." % missing_uris) self.assertEqual(medialib._progressbar.get_fraction(), 1.0) mainloop.run() self.assertEqual( medialib.store.get_n_items(), 2, "We should have one asset displayed in the MediaLibrary.") self.assertEqual(medialib.store[0].thumb_decorator.state, AssetThumbnail.PROXIED) self.assertEqual(medialib.store[1].thumb_decorator.state, AssetThumbnail.PROXIED)
def test_transition_types_loaded(self): """Checks the transition types are properly detected.""" app = common.create_pitivi_mock() widget = TransitionsListWidget(app) mainloop = common.create_main_loop() mainloop.run(until_empty=True) self.assertGreater(len(widget.storemodel), 10)
def test_load_project_clip_speed(self): sources_count = 2 clip, = self.layer.get_clips() clip.props.duration = Gst.SECOND self.timeline_container.timeline.selection.select([clip]) self.speed_box._speed_adjustment.props.value = 0.5 self.assert_applied_rate(sources_count, 0.5, 2 * Gst.SECOND) with tempfile.NamedTemporaryFile() as temp_file: uri = Gst.filename_to_uri(temp_file.name) project_manager = self.app.project_manager self.assertTrue(project_manager.save_project(uri=uri, backup=False)) mainloop = common.create_main_loop() project_manager.connect("new-project-loaded", lambda *args: mainloop.quit()) project_manager.connect("closing-project", lambda *args: True) self.assertTrue(project_manager.close_running_project()) project_manager.load_project(uri) mainloop.run() new_clip, = self.layer.get_clips() self.assertNotEqual(new_clip, clip) self.timeline_container.timeline.selection.select([new_clip]) self.assert_applied_rate(sources_count, 0.5, 2 * Gst.SECOND)
def test_asset_added_signal(self): app = common.create_pitivi() self.assertTrue(app.project_manager.newBlankProject()) project = app.project_manager.current_project proxy_manager = app.proxy_manager mainloop = common.create_main_loop() def asset_added_cb(project, asset, assets): assets.append(asset) assets = [] project.connect("asset-added", asset_added_cb, assets) def proxy_ready_cb(unused_proxy_manager, asset, proxy): mainloop.quit() proxy_manager.connect("proxy-ready", proxy_ready_cb) uris = [common.get_sample_uri("tears_of_steel.webm")] project.addUris(uris) mainloop.run() self.assertEqual(len(assets), 1, assets)
def test_loading_project_with_moved_asset(self): """Loads a project with moved asset.""" app = common.create_pitivi(proxyingStrategy=ProxyingStrategy.NOTHING) proj_uri = self.create_project_file_from_xges( app, """<ges version='0.3'> <project properties='properties;' metadatas='metadatas;'> <ressources> <asset id='file://this/is/a/moved/asset.mp4' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas' /> </ressources> </project> </ges>""") project_manager = app.project_manager medialib = medialibrary.MediaLibraryWidget(app) mainloop = common.create_main_loop() def new_project_loaded_cb(*args, **kwargs): mainloop.quit() def missing_uri_cb(project_manager, project, unused_error, asset): return common.get_sample_uri("1sec_simpsons_trailer.mp4") project_manager.connect("missing-uri", missing_uri_cb) project_manager.connect("new-project-loaded", new_project_loaded_cb) project_manager.load_project(proj_uri) with common.cloned_sample("1sec_simpsons_trailer.mp4"): mainloop.run() self.assertEqual(medialib._progressbar.get_fraction(), 1.0)
def testSetAudioProp(self): timeline = common.create_timeline_container() project = timeline.app.project_manager.current_project project.addUris([common.get_sample_uri("mp3_sample.mp3")]) audio_track = [ t for t in project.ges_timeline.tracks if isinstance(t, GES.AudioTrack) ][0] mainloop = common.create_main_loop() def progress_cb(project, progress, estimated_time): if progress == 100: mainloop.quit() project.connect_after("asset-loading-progress", progress_cb) mainloop.run() expected = Gst.Caps("audio/x-raw,channels=(int)2,rate=(int)44100") ccaps = audio_track.props.restriction_caps self.assertTrue(ccaps.is_equal_fixed(expected), "%s != %s" % (ccaps, expected)) project.audiochannels = 6 expected = Gst.Caps("audio/x-raw,channels=(int)6,rate=(int)44100") ccaps = audio_track.props.restriction_caps self.assertTrue(ccaps.is_equal_fixed(expected), "%s != %s" % (ccaps, expected))
def test_dependent_properties(self): """Checks dependent properties updating is handled correctly.""" mainloop = common.create_main_loop() app = common.create_pitivi() app.project_manager.new_blank_project() manager = EffectsPropertiesManager(app) called = False def set_child_property(prop_name, value): nonlocal called called = True self.assertEqual(prop_name, "aspect-ratio") GES.Effect.set_child_property(effect, prop_name, value) # When setting the aspect-ratio property, and the stars align, # the effect also changes the left/right properties. # Here we simulate the updating of the dependent properties. GES.Effect.set_child_property(effect, "left", 100) GES.Effect.set_child_property(effect, "right", 100) effect = GES.Effect.new("aspectratiocrop") effect.set_child_property = set_child_property effect_widget = manager.get_effect_configuration_ui(effect) widgets = {prop.name: widget for prop, widget in effect_widget.properties.items()} # Simulate the user choosing an aspect-ratio. widgets["aspect-ratio"].set_widget_value(Gst.Fraction(4, 3)) mainloop.run(until_empty=True) self.assertTrue(called)
def test_set_rendering(self): """Checks the set_rendering method.""" mainloop = common.create_main_loop() def loaded_cb(project, timeline): project.addUris([common.get_sample_uri("tears_of_steel.webm")]) def progress_cb(project, progress, estimated_time): if progress == 100: mainloop.quit() # Create a blank project and add some assets. project = common.create_project() project.connect_after("loaded", loaded_cb) project.connect_after("asset-loading-progress", progress_cb) mainloop.run() # The video settings should match tears_of_steel.webm self.assertEqual(project.videowidth, 960) self.assertEqual(project.videoheight, 400) project.render_scale = 3 # Pretend we're rendering. project.set_rendering(True) self.assertEqual(project.videowidth, 28) self.assertEqual(project.videoheight, 12) # Pretend we're not rendering anymore. project.set_rendering(False) self.assertEqual(project.videowidth, 960) self.assertEqual(project.videoheight, 400)
def load_project_with_missing_proxy(self): """Loads a project with missing proxies.""" uris = [common.get_sample_uri("1sec_simpsons_trailer.mp4")] proxy_uri = uris[0] + ".232417.proxy.mkv" PROJECT_STR = """<ges version='0.3'> <project properties='properties;' metadatas='metadatas, name=(string)"New\ Project", author=(string)Unknown, render-scale=(double)100;'> <encoding-profiles> </encoding-profiles> <ressources> <asset id='%(uri)s' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas, audio-codec=(string)"MPEG-4\ AAC\ audio", maximum-bitrate=(uint)130625, bitrate=(uint)130625, datetime=(datetime)2007-02-19T05:03:04Z, encoder=(string)Lavf54.6.100, container-format=(string)"ISO\ MP4/M4A", video-codec=(string)"H.264\ /\ AVC", file-size=(guint64)232417;' proxy-id='file:///home/thiblahute/devel/pitivi/flatpak/pitivi/tests/samples/1sec_simpsons_trailer.mp4.232417.proxy.mkv' /> <asset id='%(proxy_uri)s' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228020833;' metadatas='metadatas, container-format=(string)Matroska, audio-codec=(string)Opus, language-code=(string)en, encoder=(string)Lavf54.6.100, bitrate=(uint)64000, video-codec=(string)"Motion\ JPEG", file-size=(guint64)4695434;' /> </ressources> <timeline properties='properties, auto-transition=(boolean)true, snapping-distance=(guint64)0;' metadatas='metadatas, duration=(guint64)0;'> <track caps='video/x-raw(ANY)' track-type='4' track-id='0' properties='properties, async-handling=(boolean)false, message-forward=(boolean)true, caps=(string)"video/x-raw\(ANY\)", restriction-caps=(string)"video/x-raw\,\ width\=\(int\)720\,\ height\=\(int\)576\,\ framerate\=\(fraction\)25/1", mixing=(boolean)true;' metadatas='metadatas;'/> <track caps='audio/x-raw(ANY)' track-type='2' track-id='1' properties='properties, async-handling=(boolean)false, message-forward=(boolean)true, caps=(string)"audio/x-raw\(ANY\)", restriction-caps=(string)"audio/x-raw\,\ format\=\(string\)S32LE\,\ channels\=\(int\)2\,\ rate\=\(int\)44100\,\ layout\=\(string\)interleaved", mixing=(boolean)true;' metadatas='metadatas;'/> <layer priority='0' properties='properties, auto-transition=(boolean)true;' metadatas='metadatas, volume=(float)1;'> <clip id='0' asset-id='%(proxy_uri)s' type-name='GESUriClip' layer-priority='0' track-types='6' start='0' duration='1228000000' inpoint='0' rate='0' properties='properties, name=(string)uriclip0, mute=(boolean)false, is-image=(boolean)false;' > <source track-id='1' children-properties='properties, GstVolume::mute=(boolean)false, GstVolume::volume=(double)1;'> <binding type='direct' source_type='interpolation' property='volume' mode='1' track_id='1' values =' 0:0.10000000000000001 1228000000:0.10000000000000001 '/> </source> <source track-id='0' children-properties='properties, GstFramePositioner::alpha=(double)1, GstDeinterlace::fields=(int)0, GstFramePositioner::height=(int)720, GstDeinterlace::mode=(int)0, GstFramePositioner::posx=(int)0, GstFramePositioner::posy=(int)0, GstDeinterlace::tff=(int)0, GstFramePositioner::width=(int)1280;'> <binding type='direct' source_type='interpolation' property='alpha' mode='1' track_id='0' values =' 0:1 1228000000:1 '/> </source> </clip> </layer> <groups> </groups> </timeline> </project> </ges>""" % {"uri": uris[0], "proxy_uri": proxy_uri} app = common.create_pitivi(proxyingStrategy=ProxyingStrategy.ALL) proxy_manager = app.proxy_manager project_manager = app.project_manager mainloop = common.create_main_loop() unused, xges_path = tempfile.mkstemp(suffix=".xges") proj_uri = "file://" + os.path.abspath(xges_path) app.project_manager.saveProject(uri=proj_uri) medialib = medialibrary.MediaLibraryWidget(app) with open(proj_uri[len("file://"):], "w") as f: f.write(PROJECT_STR) # Remove proxy common.clean_proxy_samples() def closing_project_cb(*args, **kwargs): # Do not ask whether to save project on closing. return True def proxy_ready_cb(proxy_manager, asset, proxy): self.assertEqual(proxy.props.id, proxy_uri) mainloop.quit() project_manager.connect("closing-project", closing_project_cb) proxy_manager.connect_after("proxy-ready", proxy_ready_cb) app.project_manager.loadProject(proj_uri) return mainloop, app, medialib, proxy_uri
def __loading_failure(self, has_proxy): mainloop = common.create_main_loop() app = common.create_pitivi_mock(lastProjectFolder="/tmp", edgeSnapDeadband=32) app.project_manager = ProjectManager(app) mainwindow = MainWindow(app) mainwindow.viewer = mock.MagicMock() def __pm_missing_uri_cb(project_manager, project, error, asset): nonlocal mainloop nonlocal mainwindow nonlocal self nonlocal app nonlocal has_proxy with mock.patch('gi.repository.Gtk.Dialog') as dialog: failed_cb = mock.MagicMock() app.project_manager.connect("new-project-failed", failed_cb) dialog.return_value = mock.MagicMock() dialog.return_value.run = mock.MagicMock( return_value=Gtk.ResponseType.CLOSE) # Call the actual callback # pylint: disable=protected-access app.proxy_manager.checkProxyLoadingSucceeded = \ mock.MagicMock(return_value=has_proxy) mainwindow._projectManagerMissingUriCb( project_manager, project, error, asset) self.assertTrue(dialog.called) self.assertTrue(dialog.return_value.run.called) self.assertEqual(failed_cb.called, not has_proxy) # pylint: disable=protected-access app.project_manager.connect("missing-uri", mainwindow._projectManagerMissingUriCb) # pylint: disable=protected-access app.project_manager.connect("new-project-failed", mainwindow._projectManagerNewProjectFailedCb) mainwindow.destroy() mainloop.quit() # pylint: disable=protected-access disconnectAllByFunc(app.project_manager, mainwindow._projectManagerMissingUriCb) disconnectAllByFunc(app.project_manager, mainwindow._projectManagerNewProjectFailedCb) app.project_manager.connect("missing-uri", __pm_missing_uri_cb) with common.created_project_file() as uri: app.project_manager.loadProject(uri) mainloop.run()
def test_asset_added(self): uris = [common.get_sample_uri("tears_of_steel.webm")] mainloop = common.create_main_loop() def loaded_cb(unused_project, unused_timeline): self.project.addUris(uris) self.project.connect_after("loaded", loaded_cb) def progress_cb(unused_project, progress, unused_estimated_time): if progress == 100: mainloop.quit() self.project.connect_after("asset-loading-progress", progress_cb) mainloop.run() self.assertTrue(self.action_log.has_assets_operations()) self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1) self.action_log.undo() self.assertFalse(self.action_log.has_assets_operations()) self.assertEqual(len(self.project.list_assets(GES.Extractable)), 0) self.action_log.redo() self.assertTrue(self.action_log.has_assets_operations()) self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1)
def test_loading_project_with_moved_asset(self): """Loads a project with moved asset.""" app = common.create_pitivi(proxyingStrategy=ProxyingStrategy.NOTHING) proj_uri = self.create_project_file_from_xges(app, """<ges version='0.3'> <project properties='properties;' metadatas='metadatas;'> <ressources> <asset id='file://this/is/a/moved/asset.mp4' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas' /> </ressources> </project> </ges>""") project_manager = app.project_manager medialib = medialibrary.MediaLibraryWidget(app) mainloop = common.create_main_loop() def new_project_loaded_cb(*args, **kwargs): mainloop.quit() def missing_uri_cb(project_manager, project, unused_error, asset): return common.get_sample_uri("1sec_simpsons_trailer.mp4") project_manager.connect("missing-uri", missing_uri_cb) project_manager.connect("new-project-loaded", new_project_loaded_cb) project_manager.load_project(proj_uri) with common.cloned_sample("1sec_simpsons_trailer.mp4"): mainloop.run() self.assertEqual(medialib._progressbar.get_fraction(), 1.0)
def test_launching_rendering(self): """Checks no exception is raised when clicking the render button.""" timeline_container = common.create_timeline_container() app = timeline_container.app project = app.project_manager.current_project mainloop = common.create_main_loop() def asset_added_cb(project, asset): # pylint: disable=missing-docstring mainloop.quit() project.connect("asset-added", asset_added_cb) uris = [common.get_sample_uri("tears_of_steel.webm")] project.addUris(uris) mainloop.run() layer, = project.ges_timeline.get_layers() layer.add_asset(project.list_assets(GES.UriClip)[0], 0, 0, Gst.CLOCK_TIME_NONE, GES.TrackType.UNKNOWN) from pitivi.render import RenderDialog, RenderingProgressDialog with mock.patch.object(Gtk.Builder, "__new__"): dialog = RenderDialog(app, project) with mock.patch.object(dialog, "startAction"): with mock.patch.object(RenderingProgressDialog, "__new__"): with mock.patch.object(dialog, "_pipeline"): dialog._renderButtonClickedCb(None)
def test_dependent_properties(self): """Checks dependent properties updating is handled correctly.""" mainloop = common.create_main_loop() app = common.create_pitivi() app.project_manager.new_blank_project() manager = EffectsPropertiesManager(app) called = False def set_child_property(prop_name, value): nonlocal called called = True self.assertEqual(prop_name, "aspect-ratio") GES.Effect.set_child_property(effect, prop_name, value) # When setting the aspect-ratio property, and the stars align, # the effect also changes the left/right properties. # Here we simulate the updating of the dependent properties. GES.Effect.set_child_property(effect, "left", 100) GES.Effect.set_child_property(effect, "right", 100) effect = GES.Effect.new("aspectratiocrop") effect.set_child_property = set_child_property effect_widget = manager.getEffectConfigurationUI(effect) widgets = {prop.name: widget for prop, widget in effect_widget.properties.items()} # Simulate the user choosing an aspect-ratio. widgets["aspect-ratio"].setWidgetValue(Gst.Fraction(4, 3)) mainloop.run(until_empty=True) self.assertTrue(called)
def test_marker_load_project(self): """Checks marker addition.""" # TODO: When there is nothing connected to closing-project, # the default reply is "False", which means "abort saving". It should mean # "OK" to get rid off the handler. The meaning of the default (False) # must be changed def closing(unused_manager, unused_project): return True def loaded_cb(project, timeline): mainloop.quit() markers = self.timeline.get_marker_list("markers") markers.add(10) markers.add(20) self.assert_markers(markers, [(10, None), (20, None)]) project_uri = Gst.filename_to_uri(tempfile.NamedTemporaryFile().name) self.app.project_manager.save_project(project_uri) self.app.project_manager.connect("closing-project", closing) self.app.project_manager.close_running_project() project = self.app.project_manager.new_blank_project() markers = project.ges_timeline.get_marker_list("markers") self.assert_markers(markers, []) self.app.project_manager.close_running_project() project = self.app.project_manager.load_project(project_uri) project.connect("loaded", loaded_cb) mainloop = common.create_main_loop() mainloop.run() self.action_log = self.app.action_log markers = project.ges_timeline.get_marker_list("markers") self.assert_markers(markers, [(10, None), (20, None)]) ges_markers = markers.get_markers() marker1, marker2 = ges_markers with self.action_log.started("new comment"): marker1.set_string("comment", "comment 1") self.assert_markers(markers, [(10, "comment 1"), (20, None)]) with self.action_log.started("new comment"): marker2.set_string("comment", "comment 2") self.assert_markers(markers, [(10, "comment 1"), (20, "comment 2")]) for _ in range(4): self.action_log.undo() self.assert_markers(markers, [(10, "comment 1"), (20, None)]) self.action_log.undo() self.assert_markers(markers, [(10, None), (20, None)]) self.action_log.redo() self.assert_markers(markers, [(10, "comment 1"), (20, None)]) self.action_log.redo() self.assert_markers(markers, [(10, "comment 1"), (20, "comment 2")])
def __loading_failure(self, has_proxy): mainloop = common.create_main_loop() app = common.create_pitivi_mock(lastProjectFolder="/tmp", edgeSnapDeadband=32) app.project_manager = ProjectManager(app) mainwindow = MainWindow(app) mainwindow.viewer = mock.MagicMock() def __pm_missing_uri_cb(project_manager, project, error, asset): nonlocal mainloop nonlocal mainwindow nonlocal self nonlocal app nonlocal has_proxy with mock.patch('gi.repository.Gtk.Dialog') as dialog: failed_cb = mock.MagicMock() app.project_manager.connect("new-project-failed", failed_cb) dialog.return_value = mock.MagicMock() dialog.return_value.run = mock.MagicMock( return_value=Gtk.ResponseType.CLOSE) # Call the actual callback # pylint: disable=protected-access app.proxy_manager.checkProxyLoadingSucceeded = \ mock.MagicMock(return_value=has_proxy) mainwindow._projectManagerMissingUriCb(project_manager, project, error, asset) self.assertTrue(dialog.called) self.assertTrue(dialog.return_value.run.called) self.assertEqual(failed_cb.called, not has_proxy) # pylint: disable=protected-access app.project_manager.connect("missing-uri", mainwindow._projectManagerMissingUriCb) # pylint: disable=protected-access app.project_manager.connect( "new-project-failed", mainwindow._projectManagerNewProjectFailedCb) mainwindow.destroy() mainloop.quit() # pylint: disable=protected-access disconnectAllByFunc(app.project_manager, mainwindow._projectManagerMissingUriCb) disconnectAllByFunc(app.project_manager, mainwindow._projectManagerNewProjectFailedCb) app.project_manager.connect("missing-uri", __pm_missing_uri_cb) with common.created_project_file() as uri: app.project_manager.loadProject(uri) mainloop.run()
def test_select_missing_asset(self): """Exercise the MissingAssetDialog when loading a project.""" app = common.create_pitivi(proxyingStrategy=ProxyingStrategy.NOTHING, FCpreviewWidth=640, FCpreviewHeight=480) proj_uri = self.create_project_file_from_xges( app, """<ges version='0.3'> <project properties='properties;' metadatas='metadatas;'> <ressources> <asset id='file://this/is/a/moved/asset.mp4' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas' /> </ressources> </project> </ges>""") project_manager = app.project_manager # Use a cloned sample so the asset is not in GES's asset cache. # This combination of calls can lead to a mainloop freeze: # - MissingAssetDialog.get_new_uri() through the "missing-uri" signal handler, # - MissingAssetDialog.run() through MissingAssetDialog.get_new_uri(), # - GES.UriClipAsset.request_sync() through PreviewWidget.preview_uri, with common.cloned_sample("1sec_simpsons_trailer.mp4"): asset_uri = common.get_sample_uri("1sec_simpsons_trailer.mp4") mainloop = common.create_main_loop() def missing_uri_cb(project_manager, project, unused_error, asset): with mock.patch.object(MissingAssetDialog, "set_transient_for"): mad = MissingAssetDialog(app, asset, asset.get_id()) mad._chooser.select_uri(asset_uri) # Close the dialog when idle so get_new_uri does not get stuck. GLib.idle_add(mad.close) uri = mad.get_new_uri() return uri project_manager.connect("missing-uri", missing_uri_cb) preview_loaded_for_uri = "" def preview_uri(preview_widget, uri): nonlocal preview_loaded_for_uri original_preview_uri(preview_widget, uri) # If it gets past the original_preview_uri call, it's all fine! preview_loaded_for_uri = uri mainloop.quit() original_preview_uri = PreviewWidget.preview_uri PreviewWidget.preview_uri = preview_uri try: # Our mainloop timeout mechanism cannot be used, # because the mainloop gets blocked. with common.checked_operation_duration(seconds=2): project_manager.load_project(proj_uri) mainloop.run() self.assertEqual(preview_loaded_for_uri, asset_uri) finally: PreviewWidget.preview_uri = original_preview_uri
def test_removing_tags(self): self.mainloop = common.create_main_loop() self.import_assets_in_medialibrary() tag = "TAG" self.add_new_tag(tag) self.assertEqual(self.medialibrary.witnessed_tags, {tag}) # Make sure "TAG" is present in all the assets self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.PRESENT}) self.medialibrary.tags_popover.hide() self.medialibrary.flowbox.unselect_all() # Remove "TAG" from a single asset child = self.medialibrary.flowbox.get_child_at_index(0) self.medialibrary.flowbox.select_child(child) self.medialibrary.tags_button.props.active = True self.assertEqual(self.medialibrary.store[0].tags, {tag}) tags_list = self.get_tags_list() row_widget = tags_list.get_row_at_index(0) checkbox = row_widget.get_child() self.assertTrue(checkbox.props.active) checkbox.props.active = False self.medialibrary.tags_popover.hide() # Confirm "TAG" is removed from asset1 self.assertEqual(self.medialibrary.store[0].tags, set()) # Reopen the tags popover to check if "TAG" is removed from asset1 self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.ABSENT}) self.medialibrary.tags_popover.hide() # Remove inconsistent "TAG" from the selected assets self.medialibrary.flowbox.select_all() self.medialibrary.tags_button.props.active = True tags_list = self.get_tags_list() row_widget = tags_list.get_row_at_index(0) checkbox = row_widget.get_child() self.assertTrue(checkbox.props.inconsistent) # Toggle it to checked checkbox.props.active = True # Toggle it to unchecked checkbox.props.active = False self.medialibrary.tags_popover.hide() # Check if popover is empty self.medialibrary.tags_button.props.active = True tags_list = self.get_tags_list() row_widget = tags_list.get_row_at_index(0) self.assertIsNone(row_widget) self.medialibrary.tags_popover.hide() self.assertEqual(self.medialibrary.witnessed_tags, set()) for item in self.medialibrary.store: self.assertEqual(item.tags, set())
def _wait_until_project_loaded(self): # Run the mainloop so the project is set up properly so that # the timeline creates transitions automatically. mainloop = common.create_main_loop() def projectLoadedCb(unused_project, unused_timeline): mainloop.quit() self.app.project_manager.current_project.connect("loaded", projectLoadedCb) mainloop.run() self.assertTrue(self.timeline.props.auto_transition)
def __loading_failure(self, has_proxy): mainloop = common.create_main_loop() app = common.create_pitivi_mock(lastProjectFolder="/tmp", edgeSnapDeadband=32) app.project_manager = ProjectManager(app) editorperspective = EditorPerspective(app) editorperspective.setup_ui() editorperspective.viewer = mock.MagicMock() editorperspective.medialibrary._import_warning_infobar = mock.MagicMock( ) editorperspective.clipconfig.effect_expander._infobar = mock.MagicMock( ) def __pm_missing_uri_cb(project_manager, project, error, asset): nonlocal mainloop nonlocal editorperspective nonlocal self nonlocal app nonlocal has_proxy with mock.patch.object(MissingAssetDialog, "__new__") as constructor: failed_cb = mock.MagicMock() app.project_manager.connect("new-project-failed", failed_cb) dialog = constructor.return_value dialog.get_new_uri.return_value = None # Call the actual callback app.proxy_manager.checkProxyLoadingSucceeded = \ mock.MagicMock(return_value=has_proxy) editorperspective._projectManagerMissingUriCb( project_manager, project, error, asset) self.assertTrue(constructor.called) self.assertTrue(dialog.get_new_uri.called) self.assertEqual(failed_cb.called, not has_proxy) app.project_manager.connect( "missing-uri", editorperspective._projectManagerMissingUriCb) mainloop.quit() disconnectAllByFunc(app.project_manager, editorperspective._projectManagerMissingUriCb) app.project_manager.connect("missing-uri", __pm_missing_uri_cb) with common.cloned_sample(): asset_uri = common.get_sample_uri("missing.png") with common.created_project_file(asset_uri) as uri: app.project_manager.load_project(uri) mainloop.run()
def test_adding_tags(self): self.mainloop = common.create_main_loop() self.import_assets_in_medialibrary() self.medialibrary.flowbox.unselect_all() # Add a new tag "TAG" to asset1 via new tag entry field asset1 = self.medialibrary.flowbox.get_child_at_index(0) self.medialibrary.flowbox.select_child(asset1) tag = "TAG" self.add_new_tag(tag) self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.PRESENT}) self.medialibrary.tags_popover.hide() self.assertEqual(self.medialibrary.store[0].tags, {tag}) self.assertEqual(self.medialibrary.witnessed_tags, {tag}) self.medialibrary.flowbox.unselect_all() # Add an existing tag "TAG" to asset2 via toggling the unchecked mark asset2 = self.medialibrary.flowbox.get_child_at_index(1) self.medialibrary.flowbox.select_child(asset2) # Check if the tag is unchecked for now self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.ABSENT}) tags_list = self.get_tags_list() row_widget = tags_list.get_row_at_index(0) checkbox = row_widget.get_child() self.assertFalse(checkbox.props.active) checkbox.props.active = True self.medialibrary.tags_popover.hide() # Check if "TAG" is applied to asset2 self.assertEqual(self.medialibrary.store[1].tags, {tag}) # Reopen popover to check if "TAG" is present and correctly checked in asset2 self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.PRESENT}) self.medialibrary.tags_popover.hide() # We have "TAG" for both asset1 and asset2, but asset3 has no tags # Add the existing inconsistent tag to every selected asset self.medialibrary.flowbox.select_all() self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.INCONSISTENT}) tags_list = self.get_tags_list() row_widget = tags_list.get_row_at_index(0) checkbox = row_widget.get_child() # Make the tag present in all the tags checkbox.props.active = True # Reopen the tags popover to check if "TAG" is present in all assets self.medialibrary.tags_popover.hide() # Check if "TAG" is present in all the 3 assets self.medialibrary.tags_button.props.active = True self.assert_tags_popover({tag: TagState.PRESENT}) self.medialibrary.tags_popover.hide()
def test_create(self): """Exercise creating a title clip.""" timeline_container = common.create_timeline_container( titleClipLength=1) project = timeline_container._project app = timeline_container.app # Wait until the project creates a layer in the timeline. common.create_main_loop().run(until_empty=True) title_editor = TitleEditor(app) title_editor._newProjectLoadedCb(None, project) project.pipeline.getPosition = mock.Mock(return_value=0) title_editor._createCb(None) layers = timeline_container.ges_timeline.get_layers() self.assertEqual(len(layers), 1, layers) clips = layers[0].get_clips() self.assertEqual(len(clips), 1, clips) self.assertIsInstance(clips[0], GES.TitleClip)
def test_new_project_has_nothing_to_undo(self): mainloop = common.create_main_loop() def loaded_cb(project, timeline): mainloop.quit() self.project.connect_after("loaded", loaded_cb) mainloop.run() self.assertFalse(self.action_log.is_in_transaction()) self.assertFalse(self.action_log.undo_stacks)
def _scan(self, uris): """Uses the PathWalker to scan URIs.""" mainloop = common.create_main_loop() received_uris = [] def done_cb(uris): # pylint: disable=missing-docstring received_uris.extend(uris) mainloop.quit() walker = PathWalker(uris, done_cb) walker.run() mainloop.run() return received_uris
def test_loading_project_with_moved_asset_and_deleted_proxy(self): """Loads a project with moved asset as deleted proxy file.""" mainloop = common.create_main_loop() def proxy_ready_cb(unused_proxy_manager, asset, proxy): mainloop.quit() app = common.create_pitivi() app.proxy_manager.connect("proxy-ready", proxy_ready_cb) proj_uri = self.create_project_file_from_xges( app, """<ges version='0.3'> <project properties='properties;' metadatas='metadatas, name=(string)"New\ Project", author=(string)Unknown, render-scale=(double)100, format-version=(string)0.3;'> <ressources> <asset id='file:///nop/1sec_simpsons_trailer.mp4' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas, audio-codec=(string)"MPEG-4\ AAC\ audio", maximum-bitrate=(uint)130625, bitrate=(uint)130625, datetime=(datetime)2007-02-19T05:03:04Z, encoder=(string)Lavf54.6.100, container-format=(string)"ISO\ MP4/M4A", video-codec=(string)"H.264\ /\ AVC", file-size=(guint64)232417;' proxy-id='file:///nop/1sec_simpsons_trailer.mp4.232417.proxy.mkv' /> <asset id='file:///nop/1sec_simpsons_trailer.mp4.232417.proxy.mkv' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228020833;' metadatas='metadatas, container-format=(string)Matroska, audio-codec=(string)Opus, language-code=(string)en, encoder=(string)Lavf54.6.100, bitrate=(uint)64000, video-codec=(string)"Motion\ JPEG", file-size=(guint64)4694708;' /> </ressources> </project> </ges>""") project_manager = app.project_manager medialib = medialibrary.MediaLibraryWidget(app) # Remove proxy with common.cloned_sample("1sec_simpsons_trailer.mp4"): def new_project_loaded_cb(*args, **kwargs): mainloop.quit() missing_uris = [] def missing_uri_cb(project_manager, project, unused_error, asset): missing_uris.append(asset.props.id) return common.get_sample_uri("1sec_simpsons_trailer.mp4") project_manager.connect("missing-uri", missing_uri_cb) project_manager.connect("new-project-loaded", new_project_loaded_cb) project_manager.loadProject(proj_uri) mainloop.run() self.assertEqual( len(missing_uris), 1, "missing_uri_cb should be called only once, got %s." % missing_uris) self.assertEqual(medialib._progressbar.get_fraction(), 1.0) mainloop.run() self.assertEqual( len(medialib.storemodel), 1, "We should have one asset displayed in the MediaLibrary.") self.assertEqual( medialib.storemodel[0][medialibrary.COL_THUMB_DECORATOR].state, medialibrary.AssetThumbnail.PROXIED)
def test_video_toggle(self): """Checks that video toggling is reflected in the UI.""" timeline_container = common.create_timeline_container() timeline = timeline_container.timeline ges_layer = timeline.ges_timeline.append_layer() layer_controls = ges_layer.control_ui video_button = layer_controls.video_button for video_track in layer_controls.timeline_video_tracks: self.assertTrue(ges_layer.get_active_for_track(video_track)) self.assertEqual(video_button.get_image().props.icon_name, VIDEO_ICONS[True]) ges_layer.set_active_for_tracks(False, [video_track]) common.create_main_loop().run(until_empty=True) self.assertFalse(ges_layer.get_active_for_track(video_track)) self.assertEqual(video_button.get_image().props.icon_name, VIDEO_ICONS[False]) ges_layer.set_active_for_tracks(True, [video_track]) common.create_main_loop().run(until_empty=True) self.assertTrue(ges_layer.get_active_for_track(video_track)) self.assertEqual(video_button.get_image().props.icon_name, VIDEO_ICONS[True])
def __loading_failure(self, has_proxy): mainloop = common.create_main_loop() app = common.create_pitivi_mock(lastProjectFolder="/tmp", edgeSnapDeadband=32) app.project_manager = ProjectManager(app) editorperspective = EditorPerspective(app) editorperspective.setup_ui() editorperspective.viewer = mock.MagicMock() editorperspective.medialibrary._import_warning_infobar = mock.MagicMock() editorperspective.clipconfig.effect_expander._infobar = mock.MagicMock() def __pm_missing_uri_cb(project_manager, project, error, asset): nonlocal mainloop nonlocal editorperspective nonlocal self nonlocal app nonlocal has_proxy with mock.patch.object(MissingAssetDialog, "__new__") as constructor: failed_cb = mock.MagicMock() app.project_manager.connect("new-project-failed", failed_cb) dialog = constructor.return_value dialog.get_new_uri.return_value = None # Call the actual callback app.proxy_manager.checkProxyLoadingSucceeded = \ mock.MagicMock(return_value=has_proxy) editorperspective._projectManagerMissingUriCb( project_manager, project, error, asset) self.assertTrue(constructor.called) self.assertTrue(dialog.get_new_uri.called) self.assertEqual(failed_cb.called, not has_proxy) app.project_manager.connect("missing-uri", editorperspective._projectManagerMissingUriCb) mainloop.quit() disconnectAllByFunc(app.project_manager, editorperspective._projectManagerMissingUriCb) app.project_manager.connect("missing-uri", __pm_missing_uri_cb) with common.cloned_sample(): asset_uri = common.get_sample_uri("missing.png") with common.created_project_file(asset_uri) as uri: app.project_manager.load_project(uri) mainloop.run()
def testMissingUriForwarded(self): mainloop = common.create_main_loop() def missingUriCb(self, project, error, clip_asset, result): result[0] = True mainloop.quit() result = [False] self.manager.connect("missing-uri", missingUriCb, result) with common.created_project_file() as uri: self.assertTrue(self.manager.loadProject(uri)) mainloop.run() self.assertTrue(result[0], "missing-uri has not been emitted")
def test_loading_project_with_moved_assets_and_deleted_proxy(self): """Loads a project with moved asset as deleted proxy file.""" mainloop = common.create_main_loop() def proxy_ready_cb(unused_proxy_manager, asset, proxy): mainloop.quit() app = common.create_pitivi(proxyingStrategy=ProxyingStrategy.ALL) app.proxy_manager.connect("proxy-ready", proxy_ready_cb) proj_uri = self.create_project_file_from_xges(app, """<ges version='0.3'> <project properties='properties;' metadatas='metadatas, name=(string)"New\ Project", author=(string)Unknown, render-scale=(double)100, format-version=(string)0.3;'> <ressources> <asset id='file:///nop/1sec_simpsons_trailer.mp4' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228000000;' metadatas='metadatas, audio-codec=(string)"MPEG-4\ AAC\ audio", maximum-bitrate=(uint)130625, bitrate=(uint)130625, datetime=(datetime)2007-02-19T05:03:04Z, encoder=(string)Lavf54.6.100, container-format=(string)"ISO\ MP4/M4A", video-codec=(string)"H.264\ /\ AVC", file-size=(guint64)232417;' proxy-id='file:///nop/1sec_simpsons_trailer.mp4.232417.proxy.mkv' /> <asset id='file:///nop/tears_of_steel.webm' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)2003000000;' metadatas='metadatas, container-format=(string)Matroska, language-code=(string)und, application-name=(string)Lavc56.60.100, encoder=(string)"Xiph.Org\ libVorbis\ I\ 20150105\ \(\342\233\204\342\233\204\342\233\204\342\233\204\)", encoder-version=(uint)0, audio-codec=(string)Vorbis, nominal-bitrate=(uint)80000, bitrate=(uint)80000, video-codec=(string)"VP8\ video", file-size=(guint64)223340;' /> <asset id='file:///nop/1sec_simpsons_trailer.mp4.232417.proxy.mkv' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)1228020833;' metadatas='metadatas, container-format=(string)Matroska, audio-codec=(string)Opus, language-code=(string)en, encoder=(string)Lavf54.6.100, bitrate=(uint)64000, video-codec=(string)"Motion\ JPEG", file-size=(guint64)4694708;' /> <asset id='file:///nop/tears_of_steel.webm.223340.proxy.mkv' extractable-type-name='GESUriClip' properties='properties, supported-formats=(int)6, duration=(guint64)2003000000;' metadatas='metadatas, container-format=(string)Matroska, language-code=(string)und, application-name=(string)Lavc56.60.100, encoder=(string)"Xiph.Org\ libVorbis\ I\ 20150105\ \(\342\233\204\342\233\204\342\233\204\342\233\204\)", encoder-version=(uint)0, audio-codec=(string)Vorbis, nominal-bitrate=(uint)80000, bitrate=(uint)80000, video-codec=(string)"VP8\ video", file-size=(guint64)223340;' /> </ressources> </project> </ges>""") project_manager = app.project_manager medialib = medialibrary.MediaLibraryWidget(app) # Remove proxy with common.cloned_sample("1sec_simpsons_trailer.mp4", "tears_of_steel.webm"): def new_project_loaded_cb(*args, **kwargs): mainloop.quit() missing_uris = [] def missing_uri_cb(project_manager, project, unused_error, asset): missing_uris.append(asset.props.id) return common.get_sample_uri(os.path.basename(asset.props.id)) project_manager.connect("missing-uri", missing_uri_cb) project_manager.connect("new-project-loaded", new_project_loaded_cb) project_manager.load_project(proj_uri) mainloop.run() self.assertEqual(len(missing_uris), 1, "missing_uri_cb should be called only once, got %s." % missing_uris) self.assertEqual(medialib._progressbar.get_fraction(), 1.0) mainloop.run() self.assertEqual(len(medialib.storemodel), 2, "We should have one asset displayed in the MediaLibrary.") self.assertEqual(medialib.storemodel[0][medialibrary.COL_THUMB_DECORATOR].state, medialibrary.AssetThumbnail.PROXIED) self.assertEqual(medialib.storemodel[1][medialibrary.COL_THUMB_DECORATOR].state, medialibrary.AssetThumbnail.IN_PROGRESS)
def testLoaded(self): mainloop = common.create_main_loop() def new_project_loaded_cb(project_manager, project): mainloop.quit() self.manager.connect("new-project-loaded", new_project_loaded_cb) asset_uri = common.get_sample_uri("flat_colour1_640x480.png") with common.created_project_file(asset_uri=asset_uri) as uri: self.assertTrue(self.manager.loadProject(uri)) mainloop.run() project = self.manager.current_project self.assertFalse(project.at_least_one_asset_missing) self.assertTrue(project.loaded) self.assertFalse(project.hasUnsavedModifications())
def testMissingUriForwarded(self): self.setupApp(app=common.create_pitivi_mock()) mainloop = common.create_main_loop() def missingUriCb(self, project, error, clip_asset, result): result[0] = True mainloop.quit() result = [False] self.manager.connect("missing-uri", missingUriCb, result) with common.cloned_sample(): asset_uri = common.get_sample_uri("missing.png") with common.created_project_file(asset_uri) as uri: self.assertIsNotNone(self.manager.load_project(uri)) mainloop.run() self.assertTrue(result[0], "missing-uri has not been emitted")
def _customSetUp(self, project_uri=None, **kwargs): # Always make sure we start with a clean medialibrary, and no other # is connected to some assets. self.clean() self.mainloop = common.create_main_loop() self.check_no_transcoding = False self.app = common.create_pitivi_mock(**kwargs) self.app.project_manager = ProjectManager(self.app) self.medialibrary = medialibrary.MediaLibraryWidget(self.app) if project_uri: self.app.project_manager.load_project(project_uri) else: self.app.project_manager.new_blank_project() self.app.project_manager.current_project.connect( "loaded", self.projectLoadedCb) self.mainloop.run()
def testInitialization(self): mainloop = common.create_main_loop() uris = collections.deque([ common.get_sample_uri("flat_colour1_640x480.png"), common.get_sample_uri("tears_of_steel.webm"), common.get_sample_uri("1sec_simpsons_trailer.mp4")]) def loaded_cb(project, timeline): project.addUris([uris.popleft()]) def progress_cb(project, progress, estimated_time): if progress == 100: if uris: project.addUris([uris.popleft()]) else: mainloop.quit() # Create a blank project and add some assets. project = common.create_project() self.assertTrue(project._has_default_video_settings) self.assertTrue(project._has_default_audio_settings) project.connect_after("loaded", loaded_cb) project.connect_after("asset-loading-progress", progress_cb) mainloop.run() assets = project.list_assets(GES.UriClip) self.assertEqual(3, len(assets), assets) self.assertFalse(project._has_default_video_settings) self.assertFalse(project._has_default_audio_settings) # The audio settings should match tears_of_steel.webm self.assertEqual(1, project.audiochannels) self.assertEqual(44100, project.audiorate) # The video settings should match tears_of_steel.webm self.assertEqual(960, project.videowidth) self.assertEqual(400, project.videoheight) self.assertEqual(Gst.Fraction(24, 1), project.videorate) self.assertEqual(Gst.Fraction(1, 1), project.videopar)
def test_asset_added(self): mainloop = common.create_main_loop() def commit_cb(unused_action_log, stack): self.assertEqual(stack.action_group_name, "Adding assets") mainloop.quit() self.action_log.connect("commit", commit_cb) def loaded_cb(unused_project, unused_timeline): uris = [common.get_sample_uri("tears_of_steel.webm")] self.project.addUris(uris) self.project.connect_after("loaded", loaded_cb) mainloop.run() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1) self.action_log.undo() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 0) self.action_log.redo() self.assertEqual(len(self.project.list_assets(GES.Extractable)), 1)
def create_simple_project(self): """Creates a Project with a layer a clip.""" timeline_container = common.create_timeline_container() app = timeline_container.app project = app.project_manager.current_project if not project.ges_timeline.get_layers(): project.ges_timeline.append_layer() mainloop = common.create_main_loop() def asset_added_cb(project, asset): # pylint: disable=missing-docstring mainloop.quit() project.connect("asset-added", asset_added_cb) uris = [common.get_sample_uri("tears_of_steel.webm")] project.addUris(uris) mainloop.run() layer, = project.ges_timeline.get_layers() layer.add_asset(project.list_assets(GES.UriClip)[0], 0, 0, Gst.CLOCK_TIME_NONE, GES.TrackType.UNKNOWN) return project
def testSetAudioProp(self): timeline = common.create_timeline_container() project = timeline.app.project_manager.current_project project.addUris([common.get_sample_uri("mp3_sample.mp3")]) audio_track = [t for t in project.ges_timeline.tracks if isinstance(t, GES.AudioTrack)][0] mainloop = common.create_main_loop() def progress_cb(project, progress, estimated_time): if progress == 100: mainloop.quit() project.connect_after("asset-loading-progress", progress_cb) mainloop.run() expected = Gst.Caps("audio/x-raw,channels=(int)2,rate=(int)44100") ccaps = audio_track.props.restriction_caps self.assertTrue(ccaps.is_equal_fixed(expected), "%s != %s" % (ccaps, expected)) project.audiochannels = 6 expected = Gst.Caps("audio/x-raw,channels=(int)6,rate=(int)44100") ccaps = audio_track.props.restriction_caps self.assertTrue(ccaps.is_equal_fixed(expected), "%s != %s" % (ccaps, expected))