[pitivi] checkpoint. save and load implemented, now need to be hooked in pitivi.
- From: Edward Hervey <edwardrv src gnome org>
- To: svn-commits-list gnome org
- Subject: [pitivi] checkpoint. save and load implemented, now need to be hooked in pitivi.
- Date: Fri, 17 Apr 2009 09:35:45 -0400 (EDT)
commit 7000d1cab5743e9c4d915cb9250898a6a476d8ca
Author: Alessandro Decina <alessandro decina collabora co uk>
Date: Fri Mar 27 19:51:51 2009 +0100
checkpoint. save and load implemented, now need to be hooked in pitivi.
---
pitivi/formatters/etree.py | 217 ++++++++++++++++++++++++++++++++++----
tests/test_formatter.py | 252 ++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 441 insertions(+), 28 deletions(-)
diff --git a/pitivi/formatters/etree.py b/pitivi/formatters/etree.py
index dccf239..c8e4309 100644
--- a/pitivi/formatters/etree.py
+++ b/pitivi/formatters/etree.py
@@ -19,12 +19,17 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
+import gobject
+gobject.threads_init()
+import gst
+
from xml.etree.ElementTree import Element, SubElement, tostring
-from pitivi.reflect import qual
+from pitivi.reflect import qual, namedAny
from pitivi.factories.base import SourceFactory
from pitivi.factories.file import FileSourceFactory
-from pitivi.timeline.track import SourceTrackObject
+from pitivi.timeline.track import Track, SourceTrackObject
+from pitivi.timeline.timeline import Timeline, TimelineObject
from pitivi.formatters.base import Formatter
version = "0.1"
@@ -44,7 +49,13 @@ def indent(elem, level=0):
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
-class ElementTreeFormatterContext(object):
+class ElementTreeFormatterSaveContext(object):
+ def __init__(self):
+ self.streams = {}
+ self.factories = {}
+ self.track_objects = {}
+
+class ElementTreeFormatterLoadContext(object):
def __init__(self):
self.streams = {}
self.factories = {}
@@ -52,6 +63,7 @@ class ElementTreeFormatterContext(object):
class ElementTreeFormatter(Formatter):
_element_id = 0
+ _our_properties = ["id", "type"]
def _new_element_id(self):
element_id = self._element_id
@@ -59,6 +71,17 @@ class ElementTreeFormatter(Formatter):
return str(element_id)
+ def _filterElementProperties(self, element):
+ for name, value in element.attrib.iteritems():
+ if name in self._our_properties:
+ continue
+
+ yield name, value
+
+ def _parsePropertyValue(self, value):
+ # nothing to read here, move along
+ return gst.Caps("meh, name=%s" % value)[0]["name"]
+
def _saveStream(self, stream, context):
element = Element("stream")
element.attrib["id"] = self._new_element_id()
@@ -69,6 +92,17 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadStream(self, element, context):
+ id_ = element.attrib["id"]
+ klass = namedAny(element.attrib["type"])
+ caps = gst.Caps(element.attrib["caps"])
+
+ stream = klass(caps)
+
+ context.streams[id_] = stream
+
+ return stream
+
def _saveStreamRef(self, stream, context):
stream_element = context.streams[stream]
element = Element("stream-ref")
@@ -76,6 +110,9 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadStreamRef(self, element, context):
+ return context.streams[element.attrib["id"]]
+
def _saveSource(self, source, context):
element = self._saveObjectFactory(source, context)
if isinstance(source, FileSourceFactory):
@@ -83,6 +120,11 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadFactory(self, element, context):
+ klass = namedAny(element.attrib["type"])
+
+ return self._loadObjectFactory(klass, element, context)
+
def _saveObjectFactory(self, factory, context):
element = Element("source")
element.attrib["id"] = self._new_element_id()
@@ -104,6 +146,27 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadObjectFactory(self, klass, element, context):
+ # FIXME
+ if isinstance(klass, FileSourceFactory):
+ factory = FileSourceFactory(element.attrib["filename"])
+ else:
+ factory = klass()
+
+ input_streams = element.find("input-streams") or []
+ for stream_element in input_streams:
+ stream = self._loadStream(stream_element, context)
+ factory.addInputStream(stream)
+
+ output_streams = element.find("output-streams")
+ for stream_element in output_streams:
+ stream = self._loadStream(stream_element, context)
+ factory.addOutputStream(stream)
+
+ context.factories[element.attrib["id"]] = factory
+
+ return factory
+
def _saveFileSourceFactory(self, element, source, context):
element.attrib["filename"] = source.filename
@@ -115,6 +178,9 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadFactoryRef(self, element, context):
+ return context.factories[element.attrib["id"]]
+
def _saveFactories(self, factories, context):
element = Element("factories")
sources = SubElement(element, "sources")
@@ -130,8 +196,11 @@ class ElementTreeFormatter(Formatter):
element.attrib["id"] = self._new_element_id()
element.attrib["type"] = qual(track_object.__class__)
for attribute in ("start", "duration",
- "in_point", "media_duration", "priority"):
- element.attrib[attribute] = str(getattr(track_object, attribute))
+ "in_point", "media_duration"):
+ element.attrib[attribute] = \
+ str("(gint64)%s" % getattr(track_object, attribute))
+
+ element.attrib["priority"] = "(int)%s" % track_object.priority
factory_ref = \
self._saveFactoryRef(track_object.factory, context)
@@ -144,26 +213,52 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadTrackObject(self, element, context):
+ klass = namedAny(element.attrib["type"])
+
+ factory_ref = element.find("factory-ref")
+ factory = self._loadFactoryRef(factory_ref, context)
+
+ stream_ref = element.find("stream-ref")
+ stream = self._loadStreamRef(stream_ref, context)
+
+ track_object = klass(factory, stream)
+ for name, value_string in self._filterElementProperties(element):
+ value = self._parsePropertyValue(value_string)
+ setattr(track_object, name, value)
+
+ return track_object
+
def _saveTrackObjectRef(self, track_object, context):
element = Element("track-object-ref")
element.attrib["id"] = context.track_objects[track_object].attrib["id"]
return element
+ def _loadTrackObjectRef(self, element, context):
+ return context.track_objects[element.attrib["id"]]
+
def _saveTrackObjectRefs(self, track_objects, context):
element = Element("track-object-refs")
for track_object in track_objects:
- if track_object is track_object.track.default_track_object:
- continue
-
track_object_ref = self._saveTrackObjectRef(track_object, context)
element.append(track_object_ref)
return element
+ def _loadTrackObjectRefs(self, element, context):
+ track_objects = []
+ for track_object_element in element:
+ track_object = self._loadTrackObjectRef(track_object_element, context)
+ track_objects.append(track_object)
+
+ return track_objects
+
def _saveTrack(self, track, context):
element = Element("track")
+ stream_element = self._saveStream(track.stream, context)
+ element.append(stream_element)
track_objects = SubElement(element, "track-objects")
for track_object in track.track_objects:
@@ -175,32 +270,77 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadTrack(self, element, context):
+ stream_element = element.find("stream")
+ stream = self._loadStream(stream_element, context)
+
+ track = Track(stream)
+
+ track_objects_element = element.find("track-objects")
+ for track_object_element in track_objects_element:
+ track_object = self._loadTrackObject(track_object_element, context)
+ track.addTrackObject(track_object)
+
+ return track
+
+ def _saveTracks(self, tracks, context):
+ element = Element("tracks")
+ for track in tracks:
+ track_element = self._saveTrack(track, context)
+ element.append(track_element)
+
+ return element
+
+ def _loadTracks(self, element, context):
+ tracks = []
+ for track_element in element:
+ track = self._loadTrack(track_element, context)
+ tracks.append(track)
+
+ return tracks
+
def _saveTimelineObject(self, timeline_object, context):
element = Element("timeline-object")
factory_ref = self._saveFactoryRef(timeline_object.factory, context)
element.append(factory_ref)
- track_object_refs = SubElement(element, "track-object-refs")
- for track_object in timeline_object.track_objects:
- track_object_ref = self._saveTrackObjectRef(track_object, context)
- track_object_refs.append(track_object_ref)
-
+ track_object_refs = \
+ self._saveTrackObjectRefs(timeline_object.track_objects,
+ context)
+ element.append(track_object_refs)
+
return element
+ def _loadTimelineObject(self, element, context):
+ factory_ref = element.find("factory-ref")
+ factory = self._loadFactoryRef(factory_ref, context)
+
+ timeline_object = TimelineObject(factory)
+ track_object_refs_element = element.find("track-object-refs")
+ track_objects = \
+ self._loadTrackObjectRefs(track_object_refs_element, context)
+
+ for track_object in track_objects:
+ timeline_object.addTrackObject(track_object)
+
+ return timeline_object
+
def _saveTimelineObjects(self, timeline_objects, context):
element = Element("timeline-objects")
for timeline_object in timeline_objects:
- timeline_object_element = self._saveTimelineObject(timeline_object)
+ timeline_object_element = self._saveTimelineObject(timeline_object,
+ context)
element.append(timeline_object_element)
return element
- def _saveTracks(self, tracks, context):
- element = Element("tracks")
- for track in tracks:
- track_element = self._saveTrack(track, context)
- element.append(track_element)
+ def _loadTimelineObjects(self, element, context):
+ timeline_objects = []
+ for timeline_object_element in element:
+ timeline_object = \
+ self._loadTimelineObject(timeline_object_element, context)
+ timeline_objects.append(timeline_object)
- return element
+ return timeline_objects
def _saveTimeline(self, timeline, context):
element = Element("timeline")
@@ -214,6 +354,23 @@ class ElementTreeFormatter(Formatter):
return element
+ def _loadTimeline(self, element, context):
+ tracks_element = element.find("tracks")
+ tracks = self._loadTracks(tracks_element, context)
+
+ timeline_objects_element = element.find("timeline-objects")
+ timeline_objects = \
+ self._loadTimelineObjects(timeline_objects_element, context)
+
+ timeline = Timeline()
+ for track in tracks:
+ timeline.addTrack(track)
+
+ for timeline_object in timeline_objects:
+ timeline.addTimelineObject(timeline_object)
+
+ return timeline
+
def _saveMainTag(self, context):
element = Element("pitivi")
element.attrib["formatter"] = "etree"
@@ -232,3 +389,23 @@ class ElementTreeFormatter(Formatter):
root.append(timeline_element)
return root
+
+ def _loadProject(self, element, context):
+ factories_element = element.find("factories")
+ factories = self._loadFactories(factories_element, context)
+
+ timeline_element = element.find("timeline")
+ timeline = self._loadTimeline(timeline_element, context)
+
+ project = Project()
+ project.timeline = timeline
+
+ # FIXME: add factories to the sources list
+
+ for factory in factories:
+ if isinstance(factory, SourceFactory):
+ timeline.addSourceFactory(factory)
+ else:
+ raise NotImplementedError()
+
+ return project
diff --git a/tests/test_formatter.py b/tests/test_formatter.py
index 9642f25..fef6d46 100644
--- a/tests/test_formatter.py
+++ b/tests/test_formatter.py
@@ -22,10 +22,12 @@
from unittest import TestCase
from StringIO import StringIO
import gst
+from xml.etree.ElementTree import Element, SubElement, tostring
from pitivi.reflect import qual, namedAny
-from pitivi.formatters.etree import ElementTreeFormatter, \
- ElementTreeFormatterContext, version
+from pitivi.formatters.etree import ElementTreeFormatter, version, \
+ ElementTreeFormatterSaveContext, ElementTreeFormatterLoadContext, \
+ indent, tostring
from pitivi.stream import VideoStream, AudioStream
from pitivi.factories.file import FileSourceFactory
from pitivi.factories.test import VideoTestSourceFactory
@@ -36,10 +38,13 @@ from pitivi.project import Project
class FakeElementTreeFormatter(ElementTreeFormatter):
pass
+def ts(time):
+ return "(gint64)%s" % time
+
class TestFormatterSave(TestCase):
def setUp(self):
self.formatter = FakeElementTreeFormatter()
- self.context = ElementTreeFormatterContext()
+ self.context = ElementTreeFormatterSaveContext()
def testSaveStream(self):
stream = VideoStream(gst.Caps("video/x-raw-rgb, blah=meh"))
@@ -122,12 +127,12 @@ class TestFormatterSave(TestCase):
self.failUnlessEqual(element.tag, "track-object")
self.failUnlessEqual(element.attrib["type"],
qual(track_object.__class__))
- self.failUnlessEqual(element.attrib["start"], str(10 * gst.SECOND))
- self.failUnlessEqual(element.attrib["duration"], str(20 * gst.SECOND))
- self.failUnlessEqual(element.attrib["in_point"], str(5 * gst.SECOND))
+ 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"],
- str(15 * gst.SECOND))
- self.failUnlessEqual(element.attrib["priority"], str(10))
+ ts(15 * gst.SECOND))
+ self.failUnlessEqual(element.attrib["priority"], "(int)10")
self.failIfEqual(element.find("factory-ref"), None)
self.failIfEqual(element.find("stream-ref"), None)
@@ -202,6 +207,30 @@ class TestFormatterSave(TestCase):
track_object_refs = element.find("track-object-refs")
self.failUnlessEqual(len(track_object_refs), 1)
+ def testSavetimelineObjects(self):
+ video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
+ audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
+ source1 = FileSourceFactory("file1.ogg")
+
+ # these two calls are needed to populate the context for the -ref
+ # elements
+ self.formatter._saveSource(source1, self.context)
+ self.formatter._saveStream(video_stream, self.context)
+
+ track_object = SourceTrackObject(source1, video_stream,
+ start=10 * gst.SECOND, duration=20 * gst.SECOND,
+ in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
+ priority=10)
+
+ self.formatter._saveTrackObject(track_object, self.context)
+
+ timeline_object = TimelineObject(source1)
+ timeline_object.addTrackObject(track_object)
+
+ element = self.formatter._saveTimelineObjects([timeline_object],
+ self.context)
+ self.failUnlessEqual(len(element), 1)
+
def testSaveTimeline(self):
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
@@ -276,3 +305,210 @@ class TestFormatterSave(TestCase):
self.failUnlessEqual(element.tag, "pitivi")
self.failIfEqual(element.find("factories"), None)
self.failIfEqual(element.find("timeline"), None)
+
+
+class TestFormatterLoad(TestCase):
+ def setUp(self):
+ self.formatter = FakeElementTreeFormatter()
+ self.context = ElementTreeFormatterLoadContext()
+
+ def testLoadStream(self):
+ caps = gst.Caps("video/x-raw-yuv")
+ element = Element("stream")
+ element.attrib["id"] = "1"
+ element.attrib["type"] = "pitivi.stream.VideoStream"
+ element.attrib["caps"] = str(caps)
+
+ stream = self.formatter._loadStream(element, self.context)
+ self.failUnlessEqual(qual(stream.__class__), element.attrib["type"])
+ self.failUnlessEqual(str(stream.caps), str(caps))
+ self.failUnlessEqual(stream, self.context.streams["1"])
+
+ def testLoadStreamRef(self):
+ stream = VideoStream(gst.Caps("meh"))
+ self.context.streams["1"] = stream
+ element = Element("stream-ref")
+ element.attrib["id"] = "1"
+ stream1 = self.formatter._loadStreamRef(element, self.context)
+ self.failUnlessEqual(stream, stream1)
+
+ def testLoadFactory(self):
+ element = Element("source")
+ element.attrib["id"] = "1"
+ element.attrib["type"] = "pitivi.factories.test.VideoTestSourceFactory"
+ output_streams = SubElement(element, "output-streams")
+ output_stream = SubElement(output_streams, "stream")
+ caps = gst.Caps("video/x-raw-yuv")
+ output_stream.attrib["id"] = "1"
+ output_stream.attrib["type"] = "pitivi.stream.VideoStream"
+ output_stream.attrib["caps"] = str(caps)
+
+ factory = self.formatter._loadFactory(element, self.context)
+ self.failUnless(isinstance(factory, VideoTestSourceFactory))
+ self.failUnlessEqual(len(factory.output_streams), 2)
+
+ self.failUnlessEqual(self.context.factories["1"], factory)
+
+ def testLoadFactoryRef(self):
+ class Tag(object): pass
+ tag = Tag()
+ self.context.factories["1"] = tag
+ element = Element("factory-ref", id="1")
+ ret = self.formatter._loadFactoryRef(element, self.context)
+ self.failUnless(ret is tag)
+
+ def testLoadTrackObject(self):
+ element = Element("track-object",
+ type="pitivi.timeline.track.SourceTrackObject",
+ 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))
+ factory = VideoTestSourceFactory()
+ self.context.factories["1"] = factory
+ stream = VideoStream(gst.Caps("meh"))
+ self.context.streams["1"] = stream
+ factory_ref = SubElement(element, "factory-ref", id="1")
+ stream_ref = SubElement(element, "stream-ref", id="1")
+
+ track_object = self.formatter._loadTrackObject(element, self.context)
+ self.failUnless(isinstance(track_object, SourceTrackObject))
+ 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 testLoadTrackObjectRef(self):
+ class Tag(object):
+ pass
+ tag = Tag()
+ self.context.track_objects["1"] = tag
+ element = Element("track-object-ref", id="1")
+ ret = self.formatter._loadTrackObjectRef(element, self.context)
+ self.failUnless(ret is tag)
+
+ def testLoadTrack(self):
+ element = Element("track")
+ stream_element = SubElement(element, "stream", id="1",
+ type="pitivi.stream.VideoStream", caps="video/x-raw-rgb")
+
+ track_objects_element = SubElement(element, "track-objects")
+ track_object = SubElement(track_objects_element, "track-object",
+ type="pitivi.timeline.track.SourceTrackObject",
+ 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))
+ factory = VideoTestSourceFactory()
+ self.context.factories["1"] = factory
+ stream = VideoStream(gst.Caps("video/x-raw-rgb"))
+ self.context.streams["1"] = stream
+ factory_ref = SubElement(track_object, "factory-ref", id="1")
+ stream_ref = SubElement(track_object, "stream-ref", id="1")
+
+ track = self.formatter._loadTrack(element, self.context)
+
+ self.failUnlessEqual(len(track.track_objects), 2)
+ # FIXME: this is an hack
+ self.failUnlessEqual(str(track.stream), str(stream))
+
+ def testLoadTimelineObject(self):
+ video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
+ source1 = VideoTestSourceFactory()
+ self.context.factories["1"] = source1
+ self.context.track_objects["1"] = SourceTrackObject(source1, video_stream)
+
+ element = Element("timeline-object")
+ factory_ref = SubElement(element, "factory-ref", id="1")
+ stream_ref = SubElement(element, "stream-ref", id="1")
+ track_object_refs = SubElement(element, "track-object-refs")
+ track_object_ref = SubElement(track_object_refs,
+ "track-object-ref", id="1")
+
+ timeline_object = \
+ self.formatter._loadTimelineObject(element, self.context)
+
+ self.failUnlessEqual(timeline_object.factory, source1)
+ self.failUnlessEqual(len(timeline_object.track_objects), 1)
+
+ def testLoadTimeline(self):
+ timeline_element = Element("timeline")
+ tracks_element = SubElement(timeline_element, "tracks")
+ track_element = SubElement(tracks_element, "track")
+ stream_element = SubElement(track_element, "stream", id="1",
+ type="pitivi.stream.VideoStream", caps="video/x-raw-rgb")
+
+ track_objects_element = SubElement(track_element, "track-objects")
+ track_object = SubElement(track_objects_element, "track-object",
+ type="pitivi.timeline.track.SourceTrackObject",
+ 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))
+ factory = VideoTestSourceFactory()
+ self.context.factories["1"] = factory
+ stream = VideoStream(gst.Caps("video/x-raw-rgb"))
+ self.context.streams["1"] = stream
+ factory_ref = SubElement(track_object, "factory-ref", id="1")
+ stream_ref = SubElement(track_object, "stream-ref", id="1")
+
+ video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
+ source1 = VideoTestSourceFactory()
+ self.context.factories["2"] = source1
+ self.context.track_objects["1"] = SourceTrackObject(source1, video_stream)
+
+ timeline_objects_element = SubElement(timeline_element,
+ "timeline-objects")
+ timeline_object_element = \
+ SubElement(timeline_objects_element, "timeline-object")
+ factory_ref = SubElement(timeline_object_element, "factory-ref", id="1")
+ stream_ref = SubElement(timeline_object_element, "stream-ref", id="1")
+ track_object_refs = SubElement(timeline_object_element, "track-object-refs")
+ track_object_ref = SubElement(track_object_refs,
+ "track-object-ref", id="1")
+ timeline = self.formatter._loadTimeline(timeline_element, self.context)
+ self.failUnlessEqual(len(timeline.tracks), 1)
+
+ def testLoadProject(self):
+ video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
+ audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
+ source1 = VideoTestSourceFactory()
+
+ self.formatter._saveSource(source1, self.context)
+ self.formatter._saveStream(video_stream, self.context)
+
+ track_object = SourceTrackObject(source1, video_stream,
+ start=10 * gst.SECOND, duration=20 * gst.SECOND,
+ in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
+ priority=10)
+
+ self.formatter._saveTrackObject(track_object, self.context)
+
+ track = Track(video_stream)
+ track.addTrackObject(track_object)
+
+ timeline_object = TimelineObject(source1)
+ timeline_object.addTrackObject(track_object)
+
+ self.formatter._saveTimelineObject(timeline_object, self.context)
+
+ timeline = Timeline()
+ timeline.addTrack(track)
+
+ self.formatter._saveTimeline(timeline, self.context)
+
+ project = Project()
+ project.timeline = timeline
+ project.sources.addFactory("meh", source1)
+
+ element = self.formatter._saveProject(project, self.context)
+
+ self.failUnlessEqual(element.tag, "pitivi")
+ self.failIfEqual(element.find("factories"), None)
+ self.failIfEqual(element.find("timeline"), None)
+
+ indent(element)
+ f = file("/tmp/untitled.pptv", "w")
+ f.write(tostring(element))
+ f.close()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]