[pitivi] Make saving working
- From: Edward Hervey <edwardrv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] Make saving working
- Date: Wed, 22 Sep 2010 13:43:32 +0000 (UTC)
commit 6edc7c452c15eb6e5bf645db770636f6f4a5f13b
Author: Thibault Saunier <tsaunier gnome org>
Date: Tue Jul 27 00:14:57 2010 +0200
Make saving working
pitivi/application.py | 2 +-
pitivi/formatters/base.py | 3 +-
pitivi/formatters/etree.py | 88 +++++++++++++++++++++++++++++----
pitivi/formatters/format.py | 4 +-
pitivi/projectmanager.py | 11 ++--
pitivi/ui/clipproperties.py | 2 +-
pitivi/ui/effectlist.py | 2 +-
pitivi/ui/gstwidget.py | 14 +++++
pitivi/ui/timeline.py | 2 +-
tests/test_etree_formatter.py | 111 +++++++++++++++++++++++++++++++++-------
tests/test_pipeline.py | 2 +-
11 files changed, 198 insertions(+), 43 deletions(-)
---
diff --git a/pitivi/application.py b/pitivi/application.py
index c9671a0..4611143 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -139,7 +139,7 @@ class Pitivi(Loggable, Signallable):
self.effects = EffectsHandler()
self.deviceprobe = get_probe()
- self.projectManager = ProjectManager()
+ self.projectManager = ProjectManager(self.effects)
self._connectToProjectManager(self.projectManager)
self.action_log = UndoableActionLog()
diff --git a/pitivi/formatters/base.py b/pitivi/formatters/base.py
index 9ad93f5..d98d911 100644
--- a/pitivi/formatters/base.py
+++ b/pitivi/formatters/base.py
@@ -75,13 +75,14 @@ class Formatter(Signallable, Loggable):
description = "Description of the format"
ProjectClass = Project
- def __init__(self):
+ def __init__(self, avalaible_effects):
Loggable.__init__(self)
# mapping of directory changes
# key : old path
# value : new path
self.directorymapping = {}
+ self.avalaible_effects = avalaible_effects
self.project = None
#{ Load/Save methods
diff --git a/pitivi/formatters/etree.py b/pitivi/formatters/etree.py
index 34de3ec..0756584 100644
--- a/pitivi/formatters/etree.py
+++ b/pitivi/formatters/etree.py
@@ -29,7 +29,8 @@ from xml.etree.ElementTree import Element, SubElement, tostring, parse
from pitivi.reflect import qual, namedAny
from pitivi.factories.base import SourceFactory
from pitivi.factories.file import FileSourceFactory
-from pitivi.timeline.track import Track
+from pitivi.factories.operation import EffectFactory
+from pitivi.timeline.track import Track, TrackEffect
from pitivi.timeline.timeline import TimelineObject
from pitivi.formatters.base import Formatter, FormatterError
from pitivi.utils import get_filesystem_encoding
@@ -70,8 +71,8 @@ class ElementTreeFormatter(Formatter):
_element_id = 0
_our_properties = ["id", "type"]
- def __init__(self, *args, **kwargs):
- Formatter.__init__(self, *args, **kwargs)
+ def __init__(self, avalaible_effects, *args, **kwargs):
+ Formatter.__init__(self, avalaible_effects, *args, **kwargs)
self.factoriesnode = None
self.timelinenode = None
self._settingsnode = None
@@ -327,11 +328,44 @@ class ElementTreeFormatter(Formatter):
str("(gint64)%s" % getattr(track_object, attribute))
element.attrib["priority"] = "(int)%s" % track_object.priority
+ element.attrib["active"] = "(bool)%s" % track_object.active
- factory_ref = \
- self._saveFactoryRef(track_object.factory)
- stream_ref = self._saveStreamRef(track_object.stream)
+ if not isinstance(track_object.factory, EffectFactory):
+ self._saveSourceTrackObject(track_object, element)
+ else:
+ self._saveTrackEffect(track_object, element)
+
+ self._context.track_objects[track_object] = element
+
+ return element
+
+ def _saveTrackEffect(self, track_object, element):
+ effect_element = Element("effect")
+ element.append(effect_element)
+
+ factory_element = Element("factory")
+ factory_element.attrib["name"] = track_object.factory.name
+ effect_element.append(factory_element)
+
+ self._saveEffectProperties(track_object, effect_element)
+ def _saveEffectProperties(self, track_object, effect_element):
+ effect_properties = Element("gst-element-properties")
+ effect = track_object.getElement()
+ properties = gobject.list_properties(effect)
+ for prop in properties:
+ type_name = str(gobject.type_name(prop.value_type.fundamental))
+ if type_name == "GEnum":
+ value = str(effect.get_property(prop.name).value_name)
+ else:
+ value = str(effect.get_property(prop.name))
+ effect_properties.attrib[prop.name] = '(' + type_name + ')' + value
+ effect_element.append(effect_properties)
+
+
+ def _saveSourceTrackObject(self, track_object, element):
+ factory_ref = self._saveFactoryRef(track_object.factory)
+ stream_ref = self._saveStreamRef(track_object.stream)
element.append(factory_ref)
element.append(stream_ref)
interpolators = track_object.getInterpolators()
@@ -340,14 +374,48 @@ class ElementTreeFormatter(Formatter):
curves.append(self._saveInterpolator(interpolator, property))
element.append(curves)
- self._context.track_objects[track_object] = element
-
- return element
-
def _loadTrackObject(self, track, element):
self.debug("%r", element)
klass = namedAny(element.attrib["type"])
+ if klass is TrackEffect:
+ track_object = self._loadEffectTrackObject(element, klass, track)
+ else:
+ track_object = self._loadSourceTrackObject(element, klass, track)
+ return track_object
+
+ def _loadEffectTrackObject(self, element, klass, track):
+ effect_element = element.find('effect')
+ factory_name = effect_element.find('factory').attrib['name']
+ properties_elem = effect_element.find('gst-element-properties')
+ try:
+ factory = self.avalaible_effects.getFactoryFromName(factory_name)
+ except KeyError:
+ #Find a way to figure out how we could install the missing effect...
+ raise FormatterError(_("The project contains effects that are not\
+ avalaibe on the system. It can't be loaded"))
+
+ input_stream = factory.getInputStreams()
+ if not input_stream:
+ raise FormatterError("cant find effect factory input stream")
+ input_stream = input_stream[0]
+
+ track_object = klass(factory, input_stream)
+
+ track.addTrackObject(track_object)
+
+ for name, value_string in self._filterElementProperties(element):
+ value = self._parsePropertyValue(value_string)
+ setattr(track_object, name, value)
+
+ effect_gst_element = track_object.getElement()
+ for name, value in properties_elem.attrib.iteritems():
+ value = self._parsePropertyValue(value)
+ effect_gst_element.set_property(name, value)
+
+ self._context.track_objects[element.attrib["id"]] = track_object
+ return track_object
+ def _loadSourceTrackObject(self, element, klass, track):
factory_ref = element.find("factory-ref")
factory = self._loadFactoryRef(factory_ref)
diff --git a/pitivi/formatters/format.py b/pitivi/formatters/format.py
index fc63ed5..5bf591d 100644
--- a/pitivi/formatters/format.py
+++ b/pitivi/formatters/format.py
@@ -54,7 +54,7 @@ def list_formats():
"""
return _formatters
-def get_formatter_for_uri(uri):
+def get_formatter_for_uri(uri, avalaible_effects):
"""
Returns an Formatter object that can parse the given project file
@@ -64,7 +64,7 @@ def get_formatter_for_uri(uri):
"""
for klass, name, exts in _formatters:
if klass.canHandle(uri):
- return klass()
+ return klass(avalaible_effects)
def register_formatter(klass, name, extensions):
_formatters.append((klass, name, extensions))
diff --git a/pitivi/projectmanager.py b/pitivi/projectmanager.py
index b6d0ac9..463454e 100644
--- a/pitivi/projectmanager.py
+++ b/pitivi/projectmanager.py
@@ -82,12 +82,13 @@ class ProjectManager(Signallable, Loggable):
"reverting-to-saved":["project"],
}
- def __init__(self):
+ def __init__(self, avalaible_effects={}):
Signallable.__init__(self)
Loggable.__init__(self)
self.current = None
self.backup_lock = 0
+ self.avalaible_effects = avalaible_effects
def loadProject(self, uri):
""" Load the given project file"""
@@ -133,7 +134,7 @@ class ProjectManager(Signallable, Loggable):
formatter == project.format
else:
from pitivi.formatters.etree import ElementTreeFormatter
- formatter = ElementTreeFormatter()
+ formatter = ElementTreeFormatter(self.avalaible_effects)
if uri is None:
if project.uri is None:
@@ -195,12 +196,12 @@ class ProjectManager(Signallable, Loggable):
#no running project or
#project has not been modified
if self.current.uri is None \
- or not self.current.hasUnsavedModifications():
+ or not self.current.hasUnsavedModifications():
return True
if not self.emit("reverting-to-saved", self.current):
return False
- uri = self.current.uri
+ uri = self.current.uri
self.current.setModificationState(False)
self.closeRunningProject()
self.loadProject(uri)
@@ -249,7 +250,7 @@ class ProjectManager(Signallable, Loggable):
return None
def _getFormatterForUri(self, uri):
- return get_formatter_for_uri(uri)
+ return get_formatter_for_uri(uri, self.avalaible_effects)
def _connectToFormatter(self, formatter):
formatter.connect("missing-uri", self._formatterMissingURICb)
diff --git a/pitivi/ui/clipproperties.py b/pitivi/ui/clipproperties.py
index c835d86..5c69167 100644
--- a/pitivi/ui/clipproperties.py
+++ b/pitivi/ui/clipproperties.py
@@ -242,7 +242,7 @@ class EffectProperties(gtk.Expander):
def _dragDataReceivedCb(self, unused_layout, context, x, y,
selection, targetType, timestamp):
- self._factory = self.app.effects.getEffect(selection.data)
+ self._factory = self.app.effects.getFactoryFromName(selection.data)
def _dragDropCb(self, unused, context, x, y, timestamp):
if self._factory:
diff --git a/pitivi/ui/effectlist.py b/pitivi/ui/effectlist.py
index 7234c3d..f57cdce 100644
--- a/pitivi/ui/effectlist.py
+++ b/pitivi/ui/effectlist.py
@@ -165,7 +165,7 @@ class EffectList(gtk.VBox, Loggable):
def _addFactories(self, elements, effectType):
for element in elements:
- effect = self.app.effects.getEffect(element.get_name())
+ effect = self.app.effects.getFactoryFromName(element.get_name())
self.storemodel.append ([effect.icon, effect.getHumanName(),\
effect.getDescription(), effectType, effect.getCategories(),\
effect, element.get_name()])
diff --git a/pitivi/ui/gstwidget.py b/pitivi/ui/gstwidget.py
index 01f69d2..a06bb00 100644
--- a/pitivi/ui/gstwidget.py
+++ b/pitivi/ui/gstwidget.py
@@ -106,6 +106,20 @@ def make_property_widget(unused_element, prop, value=None):
selected = idx
idx = idx + 1
widget.set_active(selected)
+ elif type_name == 'GstFraction':
+ widget = gtk.HBox()
+ widget1 = gtk.SpinButton()
+ widget1.set_range(0,100)
+ widget1.set_increments(1.0, 10.0)
+ #widget1.set_value(float(value))
+ widget2 = gtk.SpinButton()
+ widget2.set_range(0,100)
+ widget2.set_increments(1.0, 10.0)
+ #widget2.set_value(float(value))
+ widget.pack_start(widget1)
+ widget.pack_start(gtk.Label("/"))
+ widget.pack_start(widget2)
+ print "%s, %s" %(value, type(value))
else:
widget = gtk.Label(type_name)
widget.set_alignment(1.0, 0.5)
diff --git a/pitivi/ui/timeline.py b/pitivi/ui/timeline.py
index 2cf7b8c..2670930 100644
--- a/pitivi/ui/timeline.py
+++ b/pitivi/ui/timeline.py
@@ -530,7 +530,7 @@ class Timeline(gtk.Table, Loggable, Zoomable):
uris = selection.data.split("\n")
self._factories = [self.project.sources.getUri(uri) for uri in uris]
else:
- self._factories = [self.app.effects.getEffect(selection.data)]
+ self._factories = [self.app.effects.getFactoryFromName(selection.data)]
context.drag_status(gtk.gdk.ACTION_COPY, timestamp)
return True
diff --git a/tests/test_etree_formatter.py b/tests/test_etree_formatter.py
index 25267d3..c8632cf 100644
--- a/tests/test_etree_formatter.py
+++ b/tests/test_etree_formatter.py
@@ -30,10 +30,13 @@ from pitivi.stream import VideoStream, AudioStream
from pitivi.factories.file import FileSourceFactory
from pitivi.factories.test import VideoTestSourceFactory, \
AudioTestSourceFactory
-from pitivi.timeline.track import Track, SourceTrackObject, Interpolator
+from pitivi.factories.operation import EffectFactory
+from pitivi.timeline.track import Track, SourceTrackObject, Interpolator,\
+ TrackEffect
from pitivi.timeline.timeline import Timeline, TimelineObject
from pitivi.project import Project
from pitivi.utils import get_controllable_properties
+from pitivi.effects import EffectsHandler
class FakeElementTreeFormatter(ElementTreeFormatter):
pass
@@ -43,7 +46,7 @@ def ts(time):
class TestFormatterSave(TestCase):
def setUp(self):
- self.formatter = FakeElementTreeFormatter()
+ self.formatter = FakeElementTreeFormatter(EffectsHandler())
def testSaveStream(self):
stream = VideoStream(gst.Caps("video/x-raw-rgb, blah=meh"))
@@ -87,13 +90,13 @@ class TestFormatterSave(TestCase):
source2.addOutputStream(video_stream)
source2.addOutputStream(audio_stream)
- factories = [source1, source2]
- element = self.formatter._saveFactories(factories)
+ source_factories = [source1, source2]
+ element = self.formatter._saveFactories(source_factories)
self.failUnlessEqual(element.tag, "factories")
sources = element.find("sources")
self.failUnlessEqual(len(sources), 2)
- # source tags are tested in testSaveSource
+ #source tags are tested in testSaveSource
def testSaveFactoryRef(self):
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
@@ -107,7 +110,43 @@ class TestFormatterSave(TestCase):
self.failUnlessEqual(element_ref.tag, "factory-ref")
self.failUnlessEqual(element_ref.attrib["id"], element.attrib["id"])
- def testSaveTrackObject(self):
+ def testSaveTrackEffect(self):
+ video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
+ audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
+
+ effect1 = EffectFactory ('identity', 'identity')
+ effect1.addOutputStream(video_stream)
+ effect1.addInputStream(video_stream)
+
+ #It is necessary to had the identity factory to the
+ #effect_factories_dictionnary
+ self.formatter.avalaible_effects._effect_factories_dict['identity'] =\
+ effect1
+ track_effect = TrackEffect(effect1, video_stream,
+ start=10 * gst.SECOND, duration=20 * gst.SECOND,
+ in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
+ priority=10)
+
+ track = Track(video_stream)
+ track.addTrackObject(track_effect)
+
+ element = self.formatter._saveTrackObject(track_effect)
+ self.failUnlessEqual(element.tag, "track-object")
+ self.failUnlessEqual(element.attrib["type"],
+ qual(track_effect.__class__))
+ self.failUnlessEqual(element.attrib["start"], ts(10 * gst.SECOND))
+ self.failUnlessEqual(element.attrib["duration"], ts(20 * gst.SECOND))
+ self.failUnlessEqual(element.attrib["in_point"], ts(5 * gst.SECOND))
+ self.failUnlessEqual(element.attrib["media_duration"],
+ ts(15 * gst.SECOND))
+ self.failUnlessEqual(element.attrib["priority"], "(int)10")
+
+ effect_element = element.find('effect')
+ self.failIfEqual(effect_element, None)
+ self.failIfEqual(effect_element.find("factory"), None)
+ self.failIfEqual(effect_element.find("properties"), None)
+
+ def testSaveTrackSource(self):
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
source1 = FileSourceFactory("file1.ogg")
@@ -118,20 +157,22 @@ class TestFormatterSave(TestCase):
self.formatter._saveSource(source1)
self.formatter._saveStream(video_stream)
- track_object = SourceTrackObject(source1, video_stream,
+
+ track_source = SourceTrackObject(source1, video_stream,
start=10 * gst.SECOND, duration=20 * gst.SECOND,
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
priority=10)
+
track = Track(video_stream)
- track.addTrackObject(track_object)
+ track.addTrackObject(track_source)
# create an interpolator and insert it into the track object
fakevol = gst.element_factory_make("volume")
prop = get_controllable_properties(fakevol)[1][1]
- volcurve = Interpolator(track_object, fakevol, prop)
- track_object.interpolators[prop.name] = (prop, volcurve)
+ volcurve = Interpolator(track_source, fakevol, prop)
+ track_source.interpolators[prop.name] = (prop, volcurve)
- # add some points to the interpolator
+ # add some points to the interpolator
value = float(0)
volcurve.start.setObjectTime(0)
volcurve.start.value = 0
@@ -141,10 +182,10 @@ class TestFormatterSave(TestCase):
volcurve.end.setObjectTime(15 * gst.SECOND)
volcurve.end.value = 15 % 2
- element = self.formatter._saveTrackObject(track_object)
+ element = self.formatter._saveTrackObject(track_source)
self.failUnlessEqual(element.tag, "track-object")
self.failUnlessEqual(element.attrib["type"],
- qual(track_object.__class__))
+ qual(track_source.__class__))
self.failUnlessEqual(element.attrib["start"], ts(10 * gst.SECOND))
self.failUnlessEqual(element.attrib["duration"], ts(20 * gst.SECOND))
self.failUnlessEqual(element.attrib["in_point"], ts(5 * gst.SECOND))
@@ -161,7 +202,7 @@ class TestFormatterSave(TestCase):
curve = curves.find("curve")
self.failIfEqual(curve, None)
self.failUnlessEqual(curve.attrib["property"], "volume")
-
+
# compute a dictionary of keyframes
saved_points = dict(((obj.attrib["time"], (obj.attrib["value"],
obj.attrib["mode"])) for obj in curve.getiterator("keyframe")))
@@ -350,7 +391,7 @@ class TestFormatterSave(TestCase):
class TestFormatterLoad(TestCase):
def setUp(self):
- self.formatter = FakeElementTreeFormatter()
+ self.formatter = FakeElementTreeFormatter(EffectsHandler())
def testLoadStream(self):
caps = gst.Caps("video/x-raw-yuv")
@@ -364,6 +405,36 @@ class TestFormatterLoad(TestCase):
self.failUnlessEqual(str(stream.caps), str(caps))
self.failUnlessEqual(stream, self.formatter._context.streams["1"])
+ def testLoadTrackEffect(self):
+ # create fake document tree
+ element = Element("track-object",\
+ type="pitivi.timeline.track.TrackEffect",
+ start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
+ in_point=ts(5 * gst.SECOND),
+ media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
+ effect_elem = SubElement(element, "effect")
+ factory_elem = SubElement(effect_elem, "factory", name="identity")
+ properties_elem = SubElement(effect_elem, "gst-element-properties", async_handling="(bool)True")
+
+ # insert our fake factory into the context
+ stream = AudioStream(gst.Caps("audio/x-raw-int"))
+ factory = EffectFactory('identity')
+ factory.addInputStream(stream)
+ factory.addOutputStream(stream)
+ self.formatter.avalaible_effects._effect_factories_dict['identity'] = factory
+
+ track = Track(stream)
+ track_object = self.formatter._loadTrackObject(track, element)
+ self.failUnless(isinstance(track_object, TrackEffect))
+ self.failUnlessEqual(track_object.factory, factory)
+ self.failUnlessEqual(track_object.stream, stream)
+
+ self.failUnlessEqual(track_object.start, 1 * gst.SECOND)
+ self.failUnlessEqual(track_object.duration, 10 * gst.SECOND)
+ self.failUnlessEqual(track_object.in_point, 5 * gst.SECOND)
+ self.failUnlessEqual(track_object.media_duration, 15 * gst.SECOND)
+ self.failUnlessEqual(track_object.priority, 5)
+
def testLoadStreamRef(self):
stream = VideoStream(gst.Caps("meh"))
self.formatter._context.streams["1"] = stream
@@ -401,7 +472,7 @@ class TestFormatterLoad(TestCase):
ret = self.formatter._loadFactoryRef(element)
self.failUnless(ret is tag)
- def testLoadTrackObject(self):
+ def testLoadTrackSource(self):
# create fake document tree
element = Element("track-object",
type="pitivi.timeline.track.SourceTrackObject",
@@ -424,11 +495,11 @@ class TestFormatterLoad(TestCase):
curves = SubElement(element, "curves")
curve = SubElement(curves, "curve", property="volume",
version="1")
- expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
+ expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
for t in xrange(1, 10))
start = SubElement(curve, "start", value="0.0", mode="2")
for time, (value, mode) in expected.iteritems():
- SubElement(curve, "keyframe", time=str(time), value=str(value),
+ SubElement(curve, "keyframe", time=str(time), value=str(value),
mode=str(mode))
end = SubElement(curve, "end", value=str(10 % 2), mode="2")
@@ -479,11 +550,11 @@ class TestFormatterLoad(TestCase):
# add a volume curve
curves = SubElement(element, "curves")
curve = SubElement(curves, "curve", property="volume")
- expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
+ expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
for t in xrange(6, 15))
start = SubElement(curve, "start", value="1.0", mode="2")
for time, (value, mode) in expected.iteritems():
- SubElement(curve, "keyframe", time=str(time), value=str(value),
+ SubElement(curve, "keyframe", time=str(time), value=str(value),
mode=str(mode))
end = SubElement(curve, "end", value="1.0", mode="2")
diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py
index 2a8d5a9..3d0ab1c 100644
--- a/tests/test_pipeline.py
+++ b/tests/test_pipeline.py
@@ -26,7 +26,7 @@ from unittest import main
from pitivi.pipeline import Pipeline, STATE_NULL, STATE_READY, STATE_PAUSED, STATE_PLAYING, PipelineError
from pitivi.action import Action, STATE_ACTIVE, STATE_NOT_ACTIVE
from pitivi.stream import AudioStream, VideoStream
-from common import TestCase, SignalMonitor, FakeSourceFactory, FakeSinkFactory
+from common import TestCase, SignalMonitor, FakeSourceFactory, FakeSinkFactory, FakeEffectFactory
class BogusAction(Action):
pass
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]