~ubuntu-branches/ubuntu/trusty/pitivi/trusty

« back to all changes in this revision

Viewing changes to tests/test_etree_formatter.py

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-07-07 13:43:47 UTC
  • mto: (6.1.9 sid) (1.2.12)
  • mto: This revision was merged to the branch mainline in revision 32.
  • Revision ID: james.westby@ubuntu.com-20110707134347-cari9kxjiakzej9z
Tags: upstream-0.14.1
ImportĀ upstreamĀ versionĀ 0.14.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# PiTiVi , Non-linear video editor
 
2
#
 
3
#       test_formatter.py
 
4
#
 
5
# Copyright (c) 2009, Alessandro Decina <alessandro.decina@collabora.co.uk>
 
6
#
 
7
# This program is free software; you can redistribute it and/or
 
8
# modify it under the terms of the GNU Lesser General Public
 
9
# License as published by the Free Software Foundation; either
 
10
# version 2.1 of the License, or (at your option) any later version.
 
11
#
 
12
# This program is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
# Lesser General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU Lesser General Public
 
18
# License along with this program; if not, write to the
 
19
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 
20
# Boston, MA 02110-1301, USA.
 
21
 
 
22
from unittest import TestCase
 
23
import gst
 
24
from xml.etree.ElementTree import Element, SubElement
 
25
 
 
26
from pitivi.reflect import qual
 
27
from pitivi.formatters.etree import ElementTreeFormatter, version,\
 
28
                                    indent, tostring
 
29
from pitivi.stream import VideoStream, AudioStream
 
30
from pitivi.factories.file import FileSourceFactory
 
31
from pitivi.factories.test import VideoTestSourceFactory, \
 
32
    AudioTestSourceFactory
 
33
from pitivi.factories.operation import EffectFactory
 
34
from pitivi.timeline.track import Track, SourceTrackObject, Interpolator,\
 
35
                                  TrackEffect
 
36
from pitivi.timeline.timeline import Timeline, TimelineObject
 
37
from pitivi.project import Project
 
38
from pitivi.utils import get_controllable_properties
 
39
from pitivi.effects import EffectsHandler
 
40
 
 
41
 
 
42
class FakeElementTreeFormatter(ElementTreeFormatter):
 
43
    pass
 
44
 
 
45
 
 
46
def ts(time):
 
47
    return "(gint64)%s" % time
 
48
 
 
49
 
 
50
class TestSerialization(TestCase):
 
51
    def setUp(self):
 
52
        self.formatter = FakeElementTreeFormatter(EffectsHandler())
 
53
 
 
54
    def testSerializeAndDeserialize(self):
 
55
        element = Element('tag')
 
56
        values_dict = {
 
57
                'str_': 'four',
 
58
                'boolean_': True,
 
59
                'float_': 4.0,
 
60
                'guint64_': 4,
 
61
                'guint64_2': 4L}
 
62
        self.formatter._serializeDict(element, values_dict)
 
63
        # Make sure that all the keys end up in element.
 
64
        for key, unused_value in values_dict.iteritems():
 
65
            self.assertTrue(key in element.attrib)
 
66
 
 
67
        deserialized_values_dict = self.formatter._deserializeDict(element)
 
68
        # Make sure that all the keys in the original dict end up in the
 
69
        # deserialized dict.
 
70
        self.assertEqual(
 
71
                set(values_dict.keys()), set(deserialized_values_dict.keys()))
 
72
        for key, value in values_dict.iteritems():
 
73
            self.assertEqual(value, deserialized_values_dict[key])
 
74
 
 
75
 
 
76
class TestFormatterSave(TestCase):
 
77
    def setUp(self):
 
78
        self.formatter = FakeElementTreeFormatter(EffectsHandler())
 
79
 
 
80
    def testSaveStream(self):
 
81
        stream = VideoStream(gst.Caps("video/x-raw-rgb, blah=meh"))
 
82
        element = self.formatter._saveStream(stream)
 
83
        self.failUnlessEqual(element.tag, "stream")
 
84
        self.failUnless("id" in element.attrib)
 
85
        self.failUnlessEqual(element.attrib["type"], qual(stream.__class__))
 
86
        self.failUnlessEqual(element.attrib["caps"], str(stream.caps))
 
87
 
 
88
    def testSaveStreamRef(self):
 
89
        # save a stream so that a mapping is created in the context
 
90
        stream = VideoStream(gst.Caps("video/x-raw-rgb, blah=meh"))
 
91
        element = self.formatter._saveStream(stream)
 
92
        element_ref = self.formatter._saveStreamRef(stream)
 
93
        self.failUnlessEqual(element_ref.tag, "stream-ref")
 
94
        self.failUnlessEqual(element_ref.attrib["id"], element.attrib["id"])
 
95
 
 
96
    def testSaveSource(self):
 
97
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
98
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
99
        source1 = FileSourceFactory("file1.ogg")
 
100
        source1.addOutputStream(video_stream)
 
101
        source1.addOutputStream(audio_stream)
 
102
        element = self.formatter._saveSource(source1)
 
103
        self.failUnlessEqual(element.tag, "source")
 
104
        self.failUnlessEqual(element.attrib["type"], qual(source1.__class__))
 
105
        self.failUnlessEqual(element.attrib["filename"], "file1.ogg")
 
106
 
 
107
        streams = element.find("output-streams")
 
108
        self.failUnlessEqual(len(streams), 2)
 
109
 
 
110
    def testSaveFactories(self):
 
111
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
112
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
113
 
 
114
        source1 = FileSourceFactory("file1.ogg")
 
115
        source1.addOutputStream(video_stream)
 
116
        source1.addOutputStream(audio_stream)
 
117
 
 
118
        source2 = FileSourceFactory("file2.ogg")
 
119
        source2.addOutputStream(video_stream)
 
120
        source2.addOutputStream(audio_stream)
 
121
 
 
122
        source_factories = [source1, source2]
 
123
        element = self.formatter._saveFactories(source_factories)
 
124
        self.failUnlessEqual(element.tag, "factories")
 
125
 
 
126
        sources = element.find("sources")
 
127
        self.failUnlessEqual(len(sources), 2)
 
128
        #source tags are tested in testSaveSource
 
129
 
 
130
    def testSaveFactoryRef(self):
 
131
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
132
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
133
        source1 = FileSourceFactory("file1.ogg")
 
134
        source1.addOutputStream(video_stream)
 
135
        source1.addOutputStream(audio_stream)
 
136
        element = self.formatter._saveSource(source1)
 
137
 
 
138
        element_ref = self.formatter._saveFactoryRef(source1)
 
139
        self.failUnlessEqual(element_ref.tag, "factory-ref")
 
140
        self.failUnlessEqual(element_ref.attrib["id"], element.attrib["id"])
 
141
 
 
142
    def testSaveTrackEffect(self):
 
143
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
144
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
145
 
 
146
        effect1 = EffectFactory('identity', 'identity')
 
147
        effect1.addOutputStream(video_stream)
 
148
        effect1.addInputStream(video_stream)
 
149
 
 
150
        #It is necessary to had the identity factory to the
 
151
        #effect_factories_dictionnary
 
152
        self.formatter.avalaible_effects._effect_factories_dict['identity'] =\
 
153
                                                                     effect1
 
154
        track_effect = TrackEffect(effect1, video_stream,
 
155
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
156
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
157
                priority=10)
 
158
 
 
159
        track = Track(video_stream)
 
160
        track.addTrackObject(track_effect)
 
161
 
 
162
        element = self.formatter._saveTrackObject(track_effect)
 
163
        self.failUnlessEqual(element.tag, "track-object")
 
164
        self.failUnlessEqual(element.attrib["type"],
 
165
                qual(track_effect.__class__))
 
166
        self.failUnlessEqual(element.attrib["start"], ts(10 * gst.SECOND))
 
167
        self.failUnlessEqual(element.attrib["duration"], ts(20 * gst.SECOND))
 
168
        self.failUnlessEqual(element.attrib["in_point"], ts(5 * gst.SECOND))
 
169
        self.failUnlessEqual(element.attrib["media_duration"],
 
170
                ts(15 * gst.SECOND))
 
171
        self.failUnlessEqual(element.attrib["priority"], "(int)10")
 
172
 
 
173
        effect_element = element.find('effect')
 
174
        self.failIfEqual(effect_element, None)
 
175
        self.failIfEqual(effect_element.find("factory"), None)
 
176
        self.failIfEqual(effect_element.find("gst-element-properties"), None)
 
177
 
 
178
    def testSaveTrackSource(self):
 
179
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
180
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
181
        source1 = FileSourceFactory("file1.ogg")
 
182
        source1.addOutputStream(video_stream)
 
183
 
 
184
        # these two calls are needed to populate the context for the -ref
 
185
        # elements
 
186
        self.formatter._saveSource(source1)
 
187
        self.formatter._saveStream(video_stream)
 
188
 
 
189
        track_source = SourceTrackObject(source1, video_stream,
 
190
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
191
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
192
                priority=10)
 
193
 
 
194
        track = Track(video_stream)
 
195
        track.addTrackObject(track_source)
 
196
 
 
197
        # create an interpolator and insert it into the track object
 
198
        fakevol = gst.element_factory_make("volume")
 
199
        prop = get_controllable_properties(fakevol)[1][1]
 
200
        volcurve = Interpolator(track_source, fakevol, prop)
 
201
        track_source.interpolators[prop.name] = (prop, volcurve)
 
202
 
 
203
        # add some points to the interpolator
 
204
        value = float(0)
 
205
        volcurve.start.setObjectTime(0)
 
206
        volcurve.start.value = 0
 
207
        for t in xrange(3, 15, 3):
 
208
            value = int(t % 2)
 
209
            volcurve.newKeyframe(t * gst.SECOND, value)
 
210
        volcurve.end.setObjectTime(15 * gst.SECOND)
 
211
        volcurve.end.value = 15 % 2
 
212
 
 
213
        element = self.formatter._saveTrackObject(track_source)
 
214
        self.failUnlessEqual(element.tag, "track-object")
 
215
        self.failUnlessEqual(element.attrib["type"],
 
216
                qual(track_source.__class__))
 
217
        self.failUnlessEqual(element.attrib["start"], ts(10 * gst.SECOND))
 
218
        self.failUnlessEqual(element.attrib["duration"], ts(20 * gst.SECOND))
 
219
        self.failUnlessEqual(element.attrib["in_point"], ts(5 * gst.SECOND))
 
220
        self.failUnlessEqual(element.attrib["media_duration"],
 
221
                ts(15 * gst.SECOND))
 
222
        self.failUnlessEqual(element.attrib["priority"], "(int)10")
 
223
 
 
224
        self.failIfEqual(element.find("factory-ref"), None)
 
225
        self.failIfEqual(element.find("stream-ref"), None)
 
226
 
 
227
        # find the interpolation keyframes
 
228
        curves = element.find("curves")
 
229
        self.failIfEqual(curves, None)
 
230
        curve = curves.find("curve")
 
231
        self.failIfEqual(curve, None)
 
232
        self.failUnlessEqual(curve.attrib["property"], "volume")
 
233
 
 
234
        # compute a dictionary of keyframes
 
235
        saved_points = dict(((obj.attrib["time"], (obj.attrib["value"],
 
236
            obj.attrib["mode"])) for obj in curve.getiterator("keyframe")))
 
237
 
 
238
        # compare this with the expected values
 
239
        expected = dict(((str(t * gst.SECOND), ("(gdouble)%s" % (t % 2), "2")) for t in
 
240
            xrange(3, 15, 3)))
 
241
        self.failUnlessEqual(expected, saved_points)
 
242
 
 
243
    def testSaveTrackObjectRef(self):
 
244
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
245
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
246
        source1 = FileSourceFactory("file1.ogg")
 
247
        source1.addOutputStream(video_stream)
 
248
 
 
249
        # these two calls are needed to populate the context for the -ref
 
250
        # elements
 
251
        self.formatter._saveSource(source1)
 
252
        self.formatter._saveStream(video_stream)
 
253
 
 
254
        track_object = SourceTrackObject(source1, video_stream,
 
255
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
256
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
257
                priority=10)
 
258
        track = Track(video_stream)
 
259
        track.addTrackObject(track_object)
 
260
 
 
261
        element = self.formatter._saveTrackObject(track_object)
 
262
        element_ref = self.formatter._saveTrackObjectRef(track_object)
 
263
        self.failUnlessEqual(element_ref.tag, "track-object-ref")
 
264
        self.failUnlessEqual(element.attrib["id"], element.attrib["id"])
 
265
 
 
266
    def testSaveTrack(self):
 
267
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
268
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
269
        source1 = VideoTestSourceFactory()
 
270
 
 
271
        # these two calls are needed to populate the context for the -ref
 
272
        # elements
 
273
        self.formatter._saveSource(source1)
 
274
        self.formatter._saveStream(video_stream)
 
275
 
 
276
        track_object = SourceTrackObject(source1, video_stream,
 
277
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
278
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
279
                priority=10)
 
280
 
 
281
        track = Track(video_stream)
 
282
        track.addTrackObject(track_object)
 
283
 
 
284
        element = self.formatter._saveTrack(track)
 
285
        self.failUnlessEqual(element.tag, "track")
 
286
        track_objects_element = element.find("track-objects")
 
287
        self.failUnlessEqual(len(track_objects_element), 1)
 
288
 
 
289
    def testSaveTimelineObject(self):
 
290
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
291
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
292
        source1 = FileSourceFactory("file1.ogg")
 
293
        source1.addOutputStream(video_stream)
 
294
 
 
295
        # these two calls are needed to populate the context for the -ref
 
296
        # elements
 
297
        self.formatter._saveSource(source1)
 
298
        self.formatter._saveStream(video_stream)
 
299
 
 
300
        track_object = SourceTrackObject(source1, video_stream,
 
301
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
302
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
303
                priority=10)
 
304
        track = Track(video_stream)
 
305
        track.addTrackObject(track_object)
 
306
 
 
307
        self.formatter._saveTrackObject(track_object)
 
308
 
 
309
        timeline_object = TimelineObject(source1)
 
310
        timeline_object.addTrackObject(track_object)
 
311
 
 
312
        element = self.formatter._saveTimelineObject(timeline_object)
 
313
        self.failUnlessEqual(element.tag, "timeline-object")
 
314
        self.failIfEqual(element.find("factory-ref"), None)
 
315
        track_object_refs = element.find("track-object-refs")
 
316
        self.failUnlessEqual(len(track_object_refs), 1)
 
317
 
 
318
    def testSavetimelineObjects(self):
 
319
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
320
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
321
        source1 = FileSourceFactory("file1.ogg")
 
322
        source1.addOutputStream(video_stream)
 
323
 
 
324
        # these two calls are needed to populate the context for the -ref
 
325
        # elements
 
326
        self.formatter._saveSource(source1)
 
327
        self.formatter._saveStream(video_stream)
 
328
 
 
329
        track_object = SourceTrackObject(source1, video_stream,
 
330
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
331
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
332
                priority=10)
 
333
        track = Track(video_stream)
 
334
        track.addTrackObject(track_object)
 
335
        self.formatter._saveTrackObject(track_object)
 
336
 
 
337
        timeline_object = TimelineObject(source1)
 
338
        timeline_object.addTrackObject(track_object)
 
339
 
 
340
        element = self.formatter._saveTimelineObjects([timeline_object])
 
341
        self.failUnlessEqual(len(element), 1)
 
342
 
 
343
    def testSaveTimeline(self):
 
344
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
345
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
346
        source1 = VideoTestSourceFactory()
 
347
        source1.addOutputStream(video_stream)
 
348
 
 
349
        self.formatter._saveSource(source1)
 
350
        self.formatter._saveStream(video_stream)
 
351
 
 
352
        track_object = SourceTrackObject(source1, video_stream,
 
353
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
354
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
355
                priority=10)
 
356
 
 
357
        track = Track(video_stream)
 
358
        track.addTrackObject(track_object)
 
359
 
 
360
        self.formatter._saveTrackObject(track_object)
 
361
 
 
362
        timeline_object = TimelineObject(source1)
 
363
        timeline_object.addTrackObject(track_object)
 
364
 
 
365
        self.formatter._saveTimelineObject(timeline_object)
 
366
 
 
367
        timeline = Timeline()
 
368
        timeline.addTrack(track)
 
369
 
 
370
        element = self.formatter._saveTimeline(timeline)
 
371
        self.failUnlessEqual(element.tag, "timeline")
 
372
        tracks = element.find("tracks")
 
373
        self.failUnlessEqual(len(tracks), 1)
 
374
 
 
375
    def testSaveMainTag(self):
 
376
        element = self.formatter._saveMainTag()
 
377
        self.failUnlessEqual(element.tag, "pitivi")
 
378
        self.failUnlessEqual(element.attrib["formatter"], "etree")
 
379
        self.failUnlessEqual(element.attrib["version"], version)
 
380
 
 
381
    def testSaveProject(self):
 
382
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
383
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
384
        source1 = VideoTestSourceFactory()
 
385
 
 
386
        self.formatter._saveSource(source1)
 
387
        self.formatter._saveStream(video_stream)
 
388
 
 
389
        track_object = SourceTrackObject(source1, video_stream,
 
390
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
391
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
392
                priority=10)
 
393
 
 
394
        track = Track(video_stream)
 
395
        track.addTrackObject(track_object)
 
396
 
 
397
        self.formatter._saveTrackObject(track_object)
 
398
 
 
399
        timeline_object = TimelineObject(source1)
 
400
        timeline_object.addTrackObject(track_object)
 
401
 
 
402
        self.formatter._saveTimelineObject(timeline_object)
 
403
 
 
404
        timeline = Timeline()
 
405
        timeline.addTrack(track)
 
406
 
 
407
        self.formatter._saveTimeline(timeline)
 
408
 
 
409
        project = Project()
 
410
        project.timeline = timeline
 
411
        project.sources.addFactory(source1)
 
412
 
 
413
        element = self.formatter._serializeProject(project)
 
414
 
 
415
        self.failUnlessEqual(element.tag, "pitivi")
 
416
        self.failIfEqual(element.find("factories"), None)
 
417
        self.failIfEqual(element.find("timeline"), None)
 
418
 
 
419
 
 
420
class TestFormatterLoad(TestCase):
 
421
    def setUp(self):
 
422
        self.formatter = FakeElementTreeFormatter(EffectsHandler())
 
423
 
 
424
    def testLoadStream(self):
 
425
        caps = gst.Caps("video/x-raw-yuv")
 
426
        element = Element("stream")
 
427
        element.attrib["id"] = "1"
 
428
        element.attrib["type"] = "pitivi.stream.VideoStream"
 
429
        element.attrib["caps"] = str(caps)
 
430
 
 
431
        stream = self.formatter._loadStream(element)
 
432
        self.failUnlessEqual(qual(stream.__class__), element.attrib["type"])
 
433
        self.failUnlessEqual(str(stream.caps), str(caps))
 
434
        self.failUnlessEqual(stream, self.formatter._context.streams["1"])
 
435
 
 
436
    def testLoadTrackEffect(self):
 
437
        # create fake document tree
 
438
        element = Element("track-object",\
 
439
                type="pitivi.timeline.track.TrackEffect",
 
440
                start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
 
441
                in_point=ts(5 * gst.SECOND),
 
442
                media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
 
443
        effect_elem = SubElement(element, "effect")
 
444
        factory_elem = SubElement(effect_elem, "factory", name="identity")
 
445
        properties_elem = SubElement(effect_elem, "gst-element-properties", sync="(bool)True")
 
446
 
 
447
        # insert our fake factory into the context
 
448
        stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
449
        factory = EffectFactory('identity')
 
450
        factory.addInputStream(stream)
 
451
        factory.addOutputStream(stream)
 
452
        self.formatter.avalaible_effects._effect_factories_dict['identity'] = factory
 
453
 
 
454
        track = Track(stream)
 
455
        track_object = self.formatter._loadTrackObject(track, element)
 
456
        self.failUnless(isinstance(track_object, TrackEffect))
 
457
        self.failUnlessEqual(track_object.factory, factory)
 
458
        self.failUnlessEqual(track_object.stream, stream)
 
459
 
 
460
        self.failUnlessEqual(track_object.start, 1 * gst.SECOND)
 
461
        self.failUnlessEqual(track_object.duration, 10 * gst.SECOND)
 
462
        self.failUnlessEqual(track_object.in_point, 5 * gst.SECOND)
 
463
        self.failUnlessEqual(track_object.media_duration, 15 * gst.SECOND)
 
464
        self.failUnlessEqual(track_object.priority, 5)
 
465
 
 
466
    def testLoadStreamRef(self):
 
467
        stream = VideoStream(gst.Caps("meh"))
 
468
        self.formatter._context.streams["1"] = stream
 
469
        element = Element("stream-ref")
 
470
        element.attrib["id"] = "1"
 
471
        stream1 = self.formatter._loadStreamRef(element)
 
472
        self.failUnlessEqual(stream, stream1)
 
473
 
 
474
    def testLoadFactory(self):
 
475
        element = Element("source")
 
476
        element.attrib["id"] = "1"
 
477
        element.attrib["type"] = "pitivi.factories.test.VideoTestSourceFactory"
 
478
        element.attrib["duration"] = 5 * gst.SECOND
 
479
        element.attrib["default_duration"] = 5 * gst.SECOND
 
480
        output_streams = SubElement(element, "output-streams")
 
481
        output_stream = SubElement(output_streams, "stream")
 
482
        caps = gst.Caps("video/x-raw-yuv")
 
483
        output_stream.attrib["id"] = "1"
 
484
        output_stream.attrib["type"] = "pitivi.stream.VideoStream"
 
485
        output_stream.attrib["caps"] = str(caps)
 
486
 
 
487
        factory = self.formatter._loadFactory(element)
 
488
        self.failUnless(isinstance(factory, VideoTestSourceFactory))
 
489
        self.failUnlessEqual(len(factory.output_streams), 2)
 
490
 
 
491
        self.failUnlessEqual(self.formatter._context.factories["1"], factory)
 
492
        self.failUnlessEqual(factory.duration, 5 * gst.SECOND)
 
493
        self.failUnlessEqual(factory.default_duration, 5 * gst.SECOND)
 
494
 
 
495
    def testLoadFactoryRef(self):
 
496
        class Tag(object):
 
497
            pass
 
498
        tag = Tag()
 
499
        self.formatter._context.factories["1"] = tag
 
500
        element = Element("factory-ref", id="1")
 
501
        ret = self.formatter._loadFactoryRef(element)
 
502
        self.failUnless(ret is tag)
 
503
 
 
504
    def testLoadTrackSource(self):
 
505
        # create fake document tree
 
506
        element = Element("track-object",
 
507
                type="pitivi.timeline.track.SourceTrackObject",
 
508
                start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
 
509
                in_point=ts(5 * gst.SECOND),
 
510
                media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
 
511
        factory_ref = SubElement(element, "factory-ref", id="1")
 
512
        stream_ref = SubElement(element, "stream-ref", id="1")
 
513
 
 
514
        # insert our fake factory into the context
 
515
        factory = AudioTestSourceFactory()
 
516
        factory.duration = 10 * gst.SECOND
 
517
        self.formatter._context.factories["1"] = factory
 
518
 
 
519
        # insert fake stream into the context
 
520
        stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
521
        self.formatter._context.streams["1"] = stream
 
522
 
 
523
        # add a volume curve
 
524
        curves = SubElement(element, "curves")
 
525
        curve = SubElement(curves, "curve", property="volume",
 
526
            version="1")
 
527
        expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
 
528
            for t in xrange(1, 10))
 
529
        start = SubElement(curve, "start", value="0.0", mode="2")
 
530
        for time, (value, mode) in expected.iteritems():
 
531
            SubElement(curve, "keyframe", time=str(time), value=str(value),
 
532
                mode=str(mode))
 
533
        end = SubElement(curve, "end", value=str(10 % 2), mode="2")
 
534
 
 
535
        track = Track(stream)
 
536
        # point gun at foot; pull trigger
 
537
        track_object = self.formatter._loadTrackObject(track, element)
 
538
        self.failUnless(isinstance(track_object, SourceTrackObject))
 
539
        self.failUnlessEqual(track_object.factory, factory)
 
540
        self.failUnlessEqual(track_object.stream, stream)
 
541
 
 
542
        self.failUnlessEqual(track_object.start, 1 * gst.SECOND)
 
543
        self.failUnlessEqual(track_object.duration, 10 * gst.SECOND)
 
544
        self.failUnlessEqual(track_object.in_point, 5 * gst.SECOND)
 
545
        self.failUnlessEqual(track_object.media_duration, 15 * gst.SECOND)
 
546
        self.failUnlessEqual(track_object.priority, 5)
 
547
 
 
548
        self.failIfEqual(track_object.interpolators, None)
 
549
        interpolator = track_object.getInterpolator("volume")
 
550
        self.failIfEqual(interpolator, None)
 
551
        curve = dict(((kf.time, (kf.value, kf.mode)) for kf in
 
552
            interpolator.getInteriorKeyframes()))
 
553
        self.failUnlessEqual(curve, expected)
 
554
 
 
555
        self.failUnlessEqual(interpolator.start.value, 0.0)
 
556
        self.failUnlessEqual(interpolator.start.time, 5 * gst.SECOND)
 
557
        self.failUnlessEqual(interpolator.end.value, 0.0)
 
558
        self.failUnlessEqual(interpolator.end.time, 15 * gst.SECOND)
 
559
 
 
560
    def testLoadInterpolatorV0(self):
 
561
        # create fake document tree
 
562
        element = Element("track-object",
 
563
                type="pitivi.timeline.track.SourceTrackObject",
 
564
                start=ts(1 * gst.SECOND), duration=ts(15 * gst.SECOND),
 
565
                in_point=ts(5 * gst.SECOND),
 
566
                media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
 
567
        factory_ref = SubElement(element, "factory-ref", id="1")
 
568
        stream_ref = SubElement(element, "stream-ref", id="1")
 
569
 
 
570
        # insert our fake factory into the context
 
571
        factory = AudioTestSourceFactory()
 
572
        factory.duration = 20 * gst.SECOND
 
573
        self.formatter._context.factories["1"] = factory
 
574
 
 
575
        # insert fake stream into the context
 
576
        stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
577
        self.formatter._context.streams["1"] = stream
 
578
 
 
579
        # add a volume curve
 
580
        curves = SubElement(element, "curves")
 
581
        curve = SubElement(curves, "curve", property="volume")
 
582
        expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
 
583
            for t in xrange(6, 15))
 
584
        start = SubElement(curve, "start", value="1.0", mode="2")
 
585
        for time, (value, mode) in expected.iteritems():
 
586
            SubElement(curve, "keyframe", time=str(time), value=str(value),
 
587
                mode=str(mode))
 
588
        end = SubElement(curve, "end", value="1.0", mode="2")
 
589
 
 
590
        track = Track(stream)
 
591
        # point gun at foot; pull trigger
 
592
        track_object = self.formatter._loadTrackObject(track, element)
 
593
        self.failIfEqual(track_object.interpolators, None)
 
594
        interpolator = track_object.getInterpolator("volume")
 
595
        self.failIfEqual(interpolator, None)
 
596
        curve = dict(((kf.time, (kf.value, kf.mode)) for kf in
 
597
            interpolator.getInteriorKeyframes()))
 
598
        self.failUnlessEqual(curve, expected)
 
599
 
 
600
        # check that start keyframe value has been properly adjusted so as not
 
601
        # to change the shape of the curve. rounding is applied here because
 
602
        # the controller seems to round to a different precision
 
603
        # than python. we just want to check that the value is "in the
 
604
        # ballpark", indicating the keyframes have been updated. If you do the
 
605
        # math you'll see that both start and end keyframe values should be
 
606
        # about 1/6
 
607
        self.failUnlessEqual(
 
608
            round(interpolator.start.value, 6),
 
609
            round((-5.0 / 6) + 1, 6))
 
610
        self.failUnlessEqual(interpolator.start.time, 5 * gst.SECOND)
 
611
 
 
612
        # check that end keyrame value has been properly adjusted so as not to
 
613
        # change the shape of the curve
 
614
        self.failUnlessEqual(interpolator.end.time, 15 * gst.SECOND)
 
615
        self.failUnlessEqual(
 
616
            round(interpolator.end.value, 6),
 
617
            round((15.0 / 6) - (7.0 / 3), 6))
 
618
 
 
619
    def testLoadTrackObjectRef(self):
 
620
        class Tag(object):
 
621
            pass
 
622
        tag = Tag()
 
623
        self.formatter._context.track_objects["1"] = tag
 
624
        element = Element("track-object-ref", id="1")
 
625
        ret = self.formatter._loadTrackObjectRef(element)
 
626
        self.failUnless(ret is tag)
 
627
 
 
628
    def testLoadTrack(self):
 
629
        # create fake document tree
 
630
        element = Element("track")
 
631
        stream_element = SubElement(element, "stream", id="1",
 
632
                type="pitivi.stream.VideoStream", caps="video/x-raw-rgb")
 
633
 
 
634
        track_objects_element = SubElement(element, "track-objects")
 
635
        track_object = SubElement(track_objects_element, "track-object",
 
636
                type="pitivi.timeline.track.SourceTrackObject",
 
637
                start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
 
638
                in_point=ts(5 * gst.SECOND),
 
639
                media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
 
640
        factory_ref = SubElement(track_object, "factory-ref", id="1")
 
641
        stream_ref = SubElement(track_object, "stream-ref", id="1")
 
642
 
 
643
        # insert fake factories and streams into current context
 
644
        factory = VideoTestSourceFactory()
 
645
        self.formatter._context.factories["1"] = factory
 
646
        stream = VideoStream(gst.Caps("video/x-raw-rgb"))
 
647
        self.formatter._context.streams["1"] = stream
 
648
 
 
649
        # point gun at foot; pull trigger
 
650
        track = self.formatter._loadTrack(element)
 
651
 
 
652
        self.failUnlessEqual(len(track.track_objects), 1)
 
653
        # FIXME: this is an hack
 
654
        self.failUnlessEqual(str(track.stream), str(stream))
 
655
 
 
656
    def testLoadTimelineObject(self):
 
657
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
658
        source1 = VideoTestSourceFactory()
 
659
        self.formatter._context.factories["1"] = source1
 
660
        self.formatter._context.track_objects["1"] = SourceTrackObject(source1, video_stream)
 
661
 
 
662
        element = Element("timeline-object")
 
663
        factory_ref = SubElement(element, "factory-ref", id="1")
 
664
        stream_ref = SubElement(element, "stream-ref", id="1")
 
665
        track_object_refs = SubElement(element, "track-object-refs")
 
666
        track_object_ref = SubElement(track_object_refs,
 
667
                "track-object-ref", id="1")
 
668
 
 
669
        timeline_object = \
 
670
                self.formatter._loadTimelineObject(element)
 
671
 
 
672
        self.failUnlessEqual(timeline_object.factory, source1)
 
673
        self.failUnlessEqual(len(timeline_object.track_objects), 1)
 
674
 
 
675
    def testLoadTimeline(self):
 
676
        # we need a project for this to work
 
677
        self.formatter.project = Project()
 
678
 
 
679
        # create fake document tree
 
680
        timeline_element = Element("timeline")
 
681
 
 
682
        tracks_element = SubElement(timeline_element, "tracks")
 
683
        track_element = SubElement(tracks_element, "track")
 
684
        stream_element = SubElement(track_element, "stream", id="1",
 
685
                type="pitivi.stream.VideoStream", caps="video/x-raw-rgb")
 
686
        track_objects_element = SubElement(track_element, "track-objects")
 
687
        track_object = SubElement(track_objects_element, "track-object",
 
688
                type="pitivi.timeline.track.SourceTrackObject",
 
689
                start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
 
690
                in_point=ts(5 * gst.SECOND),
 
691
                media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
 
692
        factory_ref = SubElement(track_object, "factory-ref", id="1")
 
693
        stream_ref = SubElement(track_object, "stream-ref", id="1")
 
694
        timeline_objects_element = SubElement(timeline_element,
 
695
                "timeline-objects")
 
696
        timeline_object_element = \
 
697
                SubElement(timeline_objects_element, "timeline-object")
 
698
        factory_ref = SubElement(timeline_object_element, "factory-ref", id="1")
 
699
        stream_ref = SubElement(timeline_object_element, "stream-ref", id="1")
 
700
        track_object_refs = SubElement(timeline_object_element, "track-object-refs")
 
701
        track_object_ref = SubElement(track_object_refs,
 
702
                "track-object-ref", id="1")
 
703
 
 
704
        # insert fake streams and factories into context
 
705
        factory = VideoTestSourceFactory()
 
706
        self.formatter._context.factories["1"] = factory
 
707
        stream = VideoStream(gst.Caps("video/x-raw-rgb"))
 
708
        self.formatter._context.streams["1"] = stream
 
709
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
710
        source1 = VideoTestSourceFactory()
 
711
        self.formatter._context.factories["2"] = source1
 
712
        self.formatter._context.track_objects["1"] = SourceTrackObject(source1, video_stream)
 
713
 
 
714
        # point gun at foot; pull trigger
 
715
        self.formatter._loadTimeline(timeline_element)
 
716
        self.failUnlessEqual(len(self.formatter.project.timeline.tracks), 1)
 
717
 
 
718
    def testLoadProject(self):
 
719
        video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
 
720
        audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
721
        source1 = VideoTestSourceFactory()
 
722
 
 
723
        self.formatter._saveSource(source1)
 
724
        self.formatter._saveStream(video_stream)
 
725
 
 
726
        track_object = SourceTrackObject(source1, video_stream,
 
727
                start=10 * gst.SECOND, duration=20 * gst.SECOND,
 
728
                in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
 
729
                priority=10)
 
730
 
 
731
        track = Track(video_stream)
 
732
        track.addTrackObject(track_object)
 
733
 
 
734
        self.formatter._saveTrackObject(track_object)
 
735
 
 
736
        timeline_object = TimelineObject(source1)
 
737
        timeline_object.addTrackObject(track_object)
 
738
 
 
739
        self.formatter._saveTimelineObject(timeline_object)
 
740
 
 
741
        timeline = Timeline()
 
742
        timeline.addTrack(track)
 
743
 
 
744
        self.formatter._saveTimeline(timeline)
 
745
 
 
746
        project = Project()
 
747
        project.timeline = timeline
 
748
        project.sources.addFactory(source1)
 
749
 
 
750
        element = self.formatter._serializeProject(project)
 
751
 
 
752
        self.failUnlessEqual(element.tag, "pitivi")
 
753
        self.failIfEqual(element.find("factories"), None)
 
754
        self.failIfEqual(element.find("timeline"), None)
 
755
 
 
756
        indent(element)
 
757
        f = file("/tmp/untitled.pptv", "w")
 
758
        f.write(tostring(element))
 
759
        f.close()
 
760
 
 
761
    ## following test is disabled until I figure out a better way of
 
762
    ## testing the mapping system.
 
763
#     def testDirectoryMapping(self):
 
764
#         pa = "file:///if/you/have/this/file/you/are/on/crack.avi"
 
765
#         pb = "file:///I/really/mean/it/you/crack.avi"
 
766
 
 
767
#         self.formatter.addMapping(pa,pb)
 
768
#         self.assertEquals(self.formatter.validateSourceURI(pa),
 
769
#                           pb)