def test_recovery(self): """Checks the recovery mechanism.""" pipe = Pipeline(common.create_pitivi_mock()) pipe.set_timeline(GES.Timeline()) pipeline_died_cb = mock.Mock() pipe.connect("died", pipeline_died_cb) with mock.patch.object(pipe, "set_state") as set_state: pipe.pause() set_state.assert_called_once_with(Gst.State.PAUSED) self.assertEqual(pipe._attempted_recoveries, 0) self.assertFalse(pipeline_died_cb.called) for i in range(MAX_RECOVERIES): with mock.patch.object(pipe, "set_state") as set_state: set_state.return_value = Gst.StateChangeReturn.SUCCESS self.post_fake_error_message(pipe) set_state.assert_has_calls( [mock.call(Gst.State.NULL), mock.call(Gst.State.PAUSED)]) self.assertEqual(set_state.call_count, 2) self.assertEqual(pipe._attempted_recoveries, i + 1) self.assertFalse(pipeline_died_cb.called) with mock.patch.object(pipe, "set_state") as set_state: self.post_fake_error_message(pipe) set_state.assert_not_called() self.assertTrue(pipeline_died_cb.called) self.assertEqual(pipe._attempted_recoveries, MAX_RECOVERIES)
def __init__(self): self.__timeline = GES.Timeline.new() self.__timeline.add_track(GES.AudioTrack.new()) self.pipeline = Pipeline() self.pipeline.set_timeline(self.__timeline) self.__clap_asset = None self.__clap_layer = None self.__asset_layer = None self.reset() GES.Asset.request_async(GES.UriClip, CLAP_ASSET, None, self.__clap_discovered_cb, None)
def __init__(self, name="", uri=None, **kwargs): """ @param name: the name of the project @param uri: the uri of the project """ Loggable.__init__(self) self.log("name:%s, uri:%s", name, uri) self.name = name self.author = "" self.year = "" self.settings = None self.description = "" self.uri = uri self.urichanged = False self.format = None self.medialibrary = MediaLibrary() self._dirty = False self.timeline = ges.timeline_new_audio_video() # We add a Selection to the timeline as there is currently # no such feature in GES self.timeline.selection = Selection() self.pipeline = Pipeline() self.pipeline.add_timeline(self.timeline) self.seeker = Seeker() self.settings = MultimediaSettings()
def __init__(self, name="", uri=None, **kwargs): """ @param name: the name of the project @param uri: the uri of the project """ Loggable.__init__(self) self.log("name:%s, uri:%s", name, uri) self.name = name self.author = "" self.year = "" self.settings = None self.description = "" self.uri = uri self.urichanged = False self.format = None self.medialibrary = MediaLibrary() self._dirty = False self.timeline = Timeline() self.pipeline = Pipeline() self.pipeline.add_timeline(self.timeline) self.seeker = Seeker() self.settings = MultimediaSettings()
def test_recovery(self): """Checks the recovery mechanism.""" pipe = Pipeline(common.create_pitivi_mock()) pipe.set_timeline(GES.Timeline()) pipeline_died_cb = mock.Mock() pipe.connect("died", pipeline_died_cb) with mock.patch.object(pipe, "set_state") as set_state: pipe.pause() set_state.assert_called_once_with(Gst.State.PAUSED) self.assertEqual(pipe._attempted_recoveries, 0) self.assertFalse(pipeline_died_cb.called) for i in range(MAX_RECOVERIES): with mock.patch.object(pipe, "set_state") as set_state: set_state.return_value = Gst.StateChangeReturn.SUCCESS self.post_fake_error_message(pipe) set_state.assert_has_calls([mock.call(Gst.State.NULL), mock.call(Gst.State.PAUSED)]) self.assertEqual(set_state.call_count, 2) self.assertEqual(pipe._attempted_recoveries, i + 1) self.assertFalse(pipeline_died_cb.called) with mock.patch.object(pipe, "set_state") as set_state: self.post_fake_error_message(pipe) set_state.assert_not_called() self.assertTrue(pipeline_died_cb.called) self.assertEqual(pipe._attempted_recoveries, MAX_RECOVERIES)
def test_commit_timeline_after(self): """Checks the recovery mechanism.""" pipe = Pipeline(common.create_pitivi_mock()) timeline = GES.Timeline() pipe.set_timeline(timeline) with mock.patch.object(pipe, "getState") as get_state: get_state.return_value = (0, Gst.State.PAUSED, 0) with mock.patch.object(timeline, "commit") as commit: with pipe.commit_timeline_after(): pipe.commit_timeline() self.assertEqual(commit.call_count, 1) with mock.patch.object(timeline, "commit") as commit: with pipe.commit_timeline_after(): self.assertEqual(pipe._prevent_commits, 1) with pipe.commit_timeline_after(): self.assertEqual(pipe._prevent_commits, 2) pipe.commit_timeline() self.assertEqual(commit.call_count, 0) self.assertEqual(commit.call_count, 1)
def test_async_done_not_received(self): """Checks the recovery when the ASYNC_DONE message timed out.""" ges_timeline = GES.Timeline.new() self.assertTrue(ges_timeline.add_track(GES.VideoTrack.new())) ges_layer = ges_timeline.append_layer() uri = common.get_sample_uri("tears_of_steel.webm") asset = GES.UriClipAsset.request_sync(uri) ges_clip = asset.extract() self.assertTrue(ges_layer.add_clip(ges_clip)) self.assertFalse(ges_timeline.is_empty()) pipe = Pipeline(app=common.create_pitivi_mock()) pipe.set_timeline(ges_timeline) self.assertFalse(pipe._busy_async) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.NOT_RECOVERING) # Pretend waiting for async-done timed out. # We mock set_state because we don't actually care about the state, # and setting the state to PAUSED could show a video window. with mock.patch.object(pipe, "set_state"): pipe._async_done_not_received_cb() # Make sure the pipeline started a watchdog timer waiting for async-done # as part of setting the state from NULL to PAUSED. self.assertTrue(pipe._busy_async) self.assertEqual(pipe._attempted_recoveries, 1) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.STARTED_RECOVERING) # Pretend the state changed to READY. message = mock.Mock() message.type = Gst.MessageType.STATE_CHANGED message.src = pipe._pipeline message.parse_state_changed.return_value = (Gst.State.NULL, Gst.State.READY, Gst.State.PAUSED) pipe._bus_message_cb(None, message) # Pretend the state changed to PAUSED. message.parse_state_changed.return_value = (Gst.State.READY, Gst.State.PAUSED, Gst.State.VOID_PENDING) self.assertEqual(pipe._next_seek, None) pipe._bus_message_cb(None, message) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.SEEKED_AFTER_RECOVERING) self.assertTrue(pipe._busy_async) # The pipeline should have tried to seek back to the last position. self.assertEqual(pipe._next_seek, 0) # Pretend the state change (to PAUSED) async operation succeeded. message.type = Gst.MessageType.ASYNC_DONE with mock.patch.object(pipe, "get_state") as get_state: get_state.return_value = (0, Gst.State.PAUSED, 0) pipe._bus_message_cb(None, message) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.NOT_RECOVERING) # Should still be busy because of seeking to _next_seek. self.assertTrue(pipe._busy_async) self.assertIsNone(pipe._next_seek) # Pretend the seek async operation finished. message.type = Gst.MessageType.ASYNC_DONE pipe._bus_message_cb(None, message) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.NOT_RECOVERING) self.assertFalse(pipe._busy_async) self.assertIsNone(pipe._next_seek)
def test_commit_timeline_after(self): """Checks the recovery mechanism.""" pipe = Pipeline(common.create_pitivi_mock()) timeline = GES.Timeline() pipe.set_timeline(timeline) with mock.patch.object(pipe, "get_state") as get_state: get_state.return_value = (0, Gst.State.PAUSED, 0) with mock.patch.object(timeline, "commit") as commit: with pipe.commit_timeline_after(): pipe.commit_timeline() self.assertEqual(commit.call_count, 1) with mock.patch.object(timeline, "commit") as commit: with pipe.commit_timeline_after(): self.assertEqual(pipe._prevent_commits, 1) with pipe.commit_timeline_after(): self.assertEqual(pipe._prevent_commits, 2) pipe.commit_timeline() self.assertEqual(commit.call_count, 0) self.assertEqual(commit.call_count, 1)
class Project(Signallable, Loggable): """The base class for PiTiVi projects @ivar name: The name of the project @type name: C{str} @ivar description: A description of the project @type description: C{str} @ivar medialibrary: The sources used by this project @type medialibrary: L{MediaLibrary} @ivar timeline: The timeline @type timeline: L{ges.Timeline} @ivar pipeline: The timeline's pipeline @type pipeline: L{Pipeline} @ivar format: The format under which the project is currently stored. @type format: L{FormatterClass} @ivar loaded: Whether the project is fully loaded or not. @type loaded: C{bool} Signals: - C{settings-changed}: The project settings changed - C{project-changed}: Modifications were made to the project """ __signals__ = { "settings-changed": ['old', 'new'], "project-changed": [], } def __init__(self, name="", uri=None, **kwargs): """ @param name: the name of the project @param uri: the uri of the project """ Loggable.__init__(self) self.log("name:%s, uri:%s", name, uri) self.name = name self.author = "" self.year = "" self.settings = None self.description = "" self.uri = uri self.urichanged = False self.format = None self.medialibrary = MediaLibrary() self._dirty = False self.timeline = ges.timeline_new_audio_video() # We add a Selection to the timeline as there is currently # no such feature in GES self.timeline.selection = Selection() self.pipeline = Pipeline() self.pipeline.add_timeline(self.timeline) self.seeker = Seeker() self.settings = MultimediaSettings() def getUri(self): return self._uri def setUri(self, uri): # FIXME support not local project if uri and not gst.uri_has_protocol(uri, "file"): # Note that this does *not* give the same result as quote_uri() self._uri = gst.uri_construct("file", uri) else: self._uri = uri uri = property(getUri, setUri) def release(self): self.pipeline.release() self.pipeline = None self.timeline = None # Project settings methods def getSettings(self): """ return the currently configured settings. """ self.debug("self.settings %s", self.settings) return self.settings def setSettings(self, settings): """ Sets the given settings as the project's settings. @param settings: The new settings for the project. @type settings: MultimediaSettings """ assert settings self.log("Setting %s as the project's settings", settings) oldsettings = self.settings self.settings = settings self.emit('settings-changed', oldsettings, settings) # Save and Load features def setModificationState(self, state): self._dirty = state if state: self.emit('project-changed') def hasUnsavedModifications(self): return self._dirty
class ClapMixer(object): def __init__(self): self.__timeline = GES.Timeline.new() self.__timeline.add_track(GES.AudioTrack.new()) self.pipeline = Pipeline() self.pipeline.set_timeline(self.__timeline) self.__clap_asset = None self.__clap_layer = None self.__asset_layer = None self.reset() GES.Asset.request_async(GES.UriClip, CLAP_ASSET, None, self.__clap_discovered_cb, None) def set_asset(self, asset): if self.__asset_layer is not None: self.__timeline.remove_layer(self.__asset_layer) if asset is None: return self.__asset_layer = self.__timeline.append_layer() self.__asset_layer.add_asset(asset, 0, 0, Gst.CLOCK_TIME_NONE, GES.TrackType.AUDIO) if self.pipeline.getState() in (Gst.State.PAUSED, Gst.State.PLAYING): self.pipeline.commit_timeline() def set_positions(self, positions): self.__positions = positions if self.__clap_asset: self.__setup_claps() def reset(self): self.pipeline.pause() # nle isn't thread-safe below PAUSED self.pipeline.get_state(timeout=Gst.CLOCK_TIME_NONE) self.pipeline.simple_seek(0) self.set_positions(None) self.set_asset(None) def __setup_claps(self): if self.__clap_layer is not None: self.__timeline.remove_layer(self.__clap_layer) self.__clap_layer = self.__timeline.append_layer() if self.__positions is None: return for position in self.__positions: self.__clap_layer.add_asset(self.__clap_asset, position, 0, Gst.CLOCK_TIME_NONE, GES.TrackType.AUDIO) if self.pipeline.getState() in (Gst.State.PAUSED, Gst.State.PLAYING): self.pipeline.commit_timeline() def __clap_discovered_cb(self, asset, result, unused): self.__clap_asset = asset self.__setup_claps()
def test_async_done_not_received(self): """Checks the recovery when the ASYNC_DONE message timed out.""" ges_timeline = GES.Timeline.new() self.assertTrue(ges_timeline.add_track(GES.VideoTrack.new())) ges_layer = ges_timeline.append_layer() uri = common.get_sample_uri("tears_of_steel.webm") asset = GES.UriClipAsset.request_sync(uri) ges_clip = asset.extract() self.assertTrue(ges_layer.add_clip(ges_clip)) self.assertFalse(ges_timeline.is_empty()) pipe = Pipeline(app=common.create_pitivi_mock()) pipe.set_timeline(ges_timeline) self.assertFalse(pipe._busy_async) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.NOT_RECOVERING) # Pretend waiting for async-done timed out. # We mock set_state because we don't actually care about the state, # and setting the state to PAUSED could show a video window. with mock.patch.object(pipe, "set_state"): pipe._async_done_not_received_cb() # Make sure the pipeline started a watchdog timer waiting for async-done # as part of setting the state from NULL to PAUSED. self.assertTrue(pipe._busy_async) self.assertEqual(pipe._attempted_recoveries, 1) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.STARTED_RECOVERING) # Pretend the state changed to READY. message = mock.Mock() message.type = Gst.MessageType.STATE_CHANGED message.src = pipe._pipeline message.parse_state_changed.return_value = (Gst.State.NULL, Gst.State.READY, Gst.State.PAUSED) pipe._busMessageCb(None, message) # Pretend the state changed to PAUSED. message.parse_state_changed.return_value = (Gst.State.READY, Gst.State.PAUSED, Gst.State.VOID_PENDING) self.assertEqual(pipe._next_seek, None) pipe._busMessageCb(None, message) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.SEEKED_AFTER_RECOVERING) self.assertTrue(pipe._busy_async) # The pipeline should have tried to seek back to the last position. self.assertEqual(pipe._next_seek, 0) # Pretend the state change (to PAUSED) async operation succeeded. message.type = Gst.MessageType.ASYNC_DONE with mock.patch.object(pipe, "get_state") as get_state: get_state.return_value = (0, Gst.State.PAUSED, 0) pipe._busMessageCb(None, message) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.NOT_RECOVERING) # Should still be busy because of seeking to _next_seek. self.assertTrue(pipe._busy_async) self.assertIsNone(pipe._next_seek) # Pretend the seek async operation finished. message.type = Gst.MessageType.ASYNC_DONE pipe._busMessageCb(None, message) self.assertEqual(pipe._recovery_state, SimplePipeline.RecoveryState.NOT_RECOVERING) self.assertFalse(pipe._busy_async) self.assertIsNone(pipe._next_seek)