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

« back to all changes in this revision

Viewing changes to tests/test_timeline.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
#       tests/test_timeline.py
 
4
#
 
5
# Copyright (c) 2008,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
import gst
 
23
 
 
24
from pitivi.factories.test import AudioTestSourceFactory
 
25
from pitivi.stream import AudioStream, VideoStream
 
26
from pitivi.timeline.timeline import Timeline, TimelineObject, TimelineError, \
 
27
        Link, TimelineEdges, MoveContext, TrimStartContext, \
 
28
        TrimEndContext
 
29
from pitivi.timeline.track import Track, SourceTrackObject, TrackEffect
 
30
from pitivi.utils import UNKNOWN_DURATION
 
31
 
 
32
from tests.common import FakeEffectFactory, FakeSourceFactory, \
 
33
        SignalMonitor, StubFactory, TestCase
 
34
 
 
35
 
 
36
class TimelineSignalMonitor(SignalMonitor):
 
37
    def __init__(self, track_object):
 
38
        SignalMonitor.__init__(self, track_object, 'start-changed',
 
39
                'duration-changed', 'in-point-changed', 'media-duration-changed')
 
40
 
 
41
 
 
42
class TestTimelineObjectAddRemoveTrackObjects(TestCase):
 
43
    def testAddRemoveTrackObjects(self):
 
44
        source_factory = StubFactory()
 
45
        timeline_object1 = TimelineObject(source_factory)
 
46
        timeline_object2 = TimelineObject(source_factory)
 
47
 
 
48
        stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
49
        source_factory.addOutputStream(stream)
 
50
        track = Track(stream)
 
51
        track_object1 = SourceTrackObject(source_factory, stream)
 
52
        track_object2 = SourceTrackObject(source_factory, stream)
 
53
 
 
54
        track.addTrackObject(track_object1)
 
55
        timeline_object1.addTrackObject(track_object1)
 
56
 
 
57
        # can't add twice
 
58
        self.failUnlessRaises(TimelineError,
 
59
                timeline_object1.addTrackObject, track_object1)
 
60
 
 
61
        # can't add to different timeline objects
 
62
        self.failUnlessRaises(TimelineError,
 
63
                timeline_object2.addTrackObject, track_object1)
 
64
 
 
65
        track.addTrackObject(track_object2)
 
66
        timeline_object1.addTrackObject(track_object2)
 
67
 
 
68
        timeline_object1.removeTrackObject(track_object1)
 
69
 
 
70
        # can't remove twice
 
71
        self.failUnlessRaises(TimelineError,
 
72
                timeline_object1.removeTrackObject, track_object1)
 
73
 
 
74
        timeline_object1.removeTrackObject(track_object2)
 
75
 
 
76
 
 
77
class TestTimelineObjectProperties(TestCase):
 
78
    def setUp(self):
 
79
        TestCase.setUp(self)
 
80
        source_factory = StubFactory()
 
81
        self.timeline_object = TimelineObject(source_factory)
 
82
        self.monitor = SignalMonitor(self.timeline_object, 'start-changed',
 
83
                'duration-changed', 'in-point-changed', 'out-point-changed',
 
84
                'media-duration-changed', 'priority-changed')
 
85
        stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
86
        source_factory.addOutputStream(stream)
 
87
        self.track = Track(stream)
 
88
        self.track_object1 = SourceTrackObject(source_factory, stream)
 
89
        self.track_object2 = SourceTrackObject(source_factory, stream)
 
90
        self.track.addTrackObject(self.track_object1)
 
91
        self.track.addTrackObject(self.track_object2)
 
92
 
 
93
    def tearDown(self):
 
94
        self.track.removeTrackObject(self.track_object1)
 
95
        self.track.removeTrackObject(self.track_object2)
 
96
        del self.track
 
97
        del self.track_object1
 
98
        del self.track_object2
 
99
        del self.monitor
 
100
        del self.timeline_object
 
101
        TestCase.tearDown(self)
 
102
 
 
103
    def testDefaultProperties(self):
 
104
        obj = self.timeline_object
 
105
        self.failUnlessEqual(obj.start, 0)
 
106
        self.failUnlessEqual(obj.duration, UNKNOWN_DURATION)
 
107
        self.failUnlessEqual(obj.in_point, 0)
 
108
        self.failUnlessEqual(obj.out_point, 0)
 
109
        self.failUnlessEqual(obj.media_duration, UNKNOWN_DURATION)
 
110
        self.failUnlessEqual(obj.priority, 0)
 
111
 
 
112
    def testChangePropertiesFromTimelineObject(self):
 
113
        timeline_object = self.timeline_object
 
114
        self.track_object1 = self.track_object1
 
115
        timeline_object.addTrackObject(self.track_object1)
 
116
 
 
117
        start = 1 * gst.SECOND
 
118
        timeline_object.start = start
 
119
        self.failUnlessEqual(timeline_object.start, start)
 
120
        self.failUnlessEqual(self.track_object1.start, start)
 
121
        self.failUnlessEqual(self.monitor.start_changed_count, 1)
 
122
 
 
123
        duration = 10 * gst.SECOND
 
124
        timeline_object.duration = duration
 
125
        self.failUnlessEqual(timeline_object.duration, duration)
 
126
        self.failUnlessEqual(self.track_object1.duration, duration)
 
127
        self.failUnlessEqual(self.monitor.duration_changed_count, 1)
 
128
 
 
129
        in_point = 5 * gst.SECOND
 
130
        timeline_object.in_point = in_point
 
131
        self.failUnlessEqual(timeline_object.in_point, in_point)
 
132
        self.failUnlessEqual(self.track_object1.in_point, in_point)
 
133
        self.failUnlessEqual(self.monitor.in_point_changed_count, 1)
 
134
 
 
135
        media_duration = 5 * gst.SECOND
 
136
        timeline_object.media_duration = media_duration
 
137
        self.failUnlessEqual(timeline_object.media_duration, media_duration)
 
138
        self.failUnlessEqual(self.track_object1.media_duration, media_duration)
 
139
        self.failUnlessEqual(self.monitor.media_duration_changed_count, 1)
 
140
        self.failUnlessEqual(timeline_object.out_point,
 
141
                in_point + media_duration)
 
142
        self.failUnlessEqual(self.track_object1.out_point,
 
143
                in_point + media_duration)
 
144
        # FIXME
 
145
        #self.failUnlessEqual(self.monitor.out_point_changed_count, 1)
 
146
 
 
147
        priority = 100
 
148
        timeline_object.priority = priority
 
149
        self.failUnlessEqual(timeline_object.priority, priority)
 
150
        self.failUnlessEqual(self.track_object1.priority, priority)
 
151
        self.failUnlessEqual(self.monitor.priority_changed_count, 1)
 
152
 
 
153
    def testChangePropertiesFromTimelineObject2(self):
 
154
        timeline_object = self.timeline_object
 
155
        self.track_object1 = self.track_object1
 
156
        timeline_object.addTrackObject(self.track_object1)
 
157
        timeline_object.addTrackObject(self.track_object2)
 
158
 
 
159
        start = 1 * gst.SECOND
 
160
        timeline_object.start = start
 
161
        self.failUnlessEqual(timeline_object.start, start)
 
162
        self.failUnlessEqual(self.track_object1.start, start)
 
163
        self.failUnlessEqual(self.track_object2.start, start)
 
164
        self.failUnlessEqual(self.monitor.start_changed_count, 1)
 
165
 
 
166
        duration = 10 * gst.SECOND
 
167
        timeline_object.duration = duration
 
168
        self.failUnlessEqual(timeline_object.duration, duration)
 
169
        self.failUnlessEqual(self.track_object1.duration, duration)
 
170
        self.failUnlessEqual(self.track_object2.duration, duration)
 
171
        self.failUnlessEqual(self.monitor.duration_changed_count, 1)
 
172
 
 
173
        in_point = 5 * gst.SECOND
 
174
        timeline_object.in_point = in_point
 
175
        self.failUnlessEqual(timeline_object.in_point, in_point)
 
176
        self.failUnlessEqual(self.track_object1.in_point, in_point)
 
177
        self.failUnlessEqual(self.track_object2.in_point, in_point)
 
178
        self.failUnlessEqual(self.monitor.in_point_changed_count, 1)
 
179
 
 
180
        media_duration = 5 * gst.SECOND
 
181
        timeline_object.media_duration = media_duration
 
182
        self.failUnlessEqual(timeline_object.media_duration, media_duration)
 
183
        self.failUnlessEqual(self.track_object1.media_duration, media_duration)
 
184
        self.failUnlessEqual(self.track_object2.media_duration, media_duration)
 
185
        self.failUnlessEqual(self.monitor.media_duration_changed_count, 1)
 
186
 
 
187
        priority = 100
 
188
        timeline_object.priority = priority
 
189
        self.failUnlessEqual(timeline_object.priority, priority)
 
190
        self.failUnlessEqual(self.track_object1.priority, priority)
 
191
        self.failUnlessEqual(self.track_object2.priority, priority)
 
192
        self.failUnlessEqual(self.monitor.priority_changed_count, 1)
 
193
 
 
194
    def testChangePropertiesFromTrackObject(self):
 
195
        timeline_object = self.timeline_object
 
196
        track_object = self.track_object1
 
197
        timeline_object.addTrackObject(track_object)
 
198
 
 
199
        start = 1 * gst.SECOND
 
200
        track_object.start = start
 
201
        self.failUnlessEqual(timeline_object.start, start)
 
202
        self.failUnlessEqual(self.monitor.start_changed_count, 1)
 
203
 
 
204
        duration = 10 * gst.SECOND
 
205
        track_object.duration = duration
 
206
        self.failUnlessEqual(timeline_object.duration, duration)
 
207
        self.failUnlessEqual(self.monitor.duration_changed_count, 1)
 
208
 
 
209
        in_point = 5 * gst.SECOND
 
210
        track_object.in_point = in_point
 
211
        self.failUnlessEqual(timeline_object.in_point, in_point)
 
212
        self.failUnlessEqual(self.monitor.in_point_changed_count, 1)
 
213
 
 
214
        media_duration = 5 * gst.SECOND
 
215
        track_object.media_duration = media_duration
 
216
        self.failUnlessEqual(timeline_object.media_duration, media_duration)
 
217
        self.failUnlessEqual(self.monitor.media_duration_changed_count, 1)
 
218
 
 
219
        priority = 100
 
220
        track_object.priority = priority
 
221
        self.failUnlessEqual(timeline_object.priority, priority)
 
222
        self.failUnlessEqual(self.monitor.priority_changed_count, 1)
 
223
 
 
224
    def testSplit(self):
 
225
        obj = self.timeline_object
 
226
        track_object = self.track_object1
 
227
        obj.addTrackObject(track_object)
 
228
 
 
229
        obj.start = 3 * gst.SECOND
 
230
        obj.duration = 10 * gst.SECOND
 
231
 
 
232
        monitor = TimelineSignalMonitor(obj)
 
233
 
 
234
        self.failUnlessRaises(TimelineError, obj.split, 2 * gst.SECOND)
 
235
        self.failUnlessRaises(TimelineError, obj.split, 14 * gst.SECOND)
 
236
 
 
237
        # should these be possible (ie create empty objects) ?
 
238
        self.failUnlessRaises(TimelineError, obj.split, 3 * gst.SECOND)
 
239
        self.failUnlessRaises(TimelineError, obj.split, 13 * gst.SECOND)
 
240
 
 
241
        # split at 4s should result in:
 
242
        # obj (start 3, end 4) other1 (start 4, end 13)
 
243
        other1 = obj.split(4 * gst.SECOND)
 
244
 
 
245
        self.failUnlessEqual(obj.start, 3 * gst.SECOND)
 
246
        self.failUnlessEqual(obj.duration, 1 * gst.SECOND)
 
247
 
 
248
        self.failUnlessEqual(other1.start, 4 * gst.SECOND)
 
249
        self.failUnlessEqual(other1.duration, 9 * gst.SECOND)
 
250
 
 
251
        self.failUnlessEqual(monitor.start_changed_count, 0)
 
252
        self.failUnlessEqual(monitor.duration_changed_count, 1)
 
253
 
 
254
        # split again other1
 
255
        monitor = TimelineSignalMonitor(other1)
 
256
 
 
257
        other2 = other1.split(11 * gst.SECOND)
 
258
        self.failUnlessEqual(other1.start, 4 * gst.SECOND)
 
259
        self.failUnlessEqual(other1.duration, 7 * gst.SECOND)
 
260
 
 
261
        self.failUnlessEqual(other2.start, 11 * gst.SECOND)
 
262
        self.failUnlessEqual(other2.duration, 2 * gst.SECOND)
 
263
 
 
264
        self.failUnlessEqual(monitor.start_changed_count, 0)
 
265
        self.failUnlessEqual(monitor.duration_changed_count, 1)
 
266
 
 
267
 
 
268
class TestTimelineAddRemoveTracks(TestCase):
 
269
    def testAddRemoveTracks(self):
 
270
        stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
271
        track1 = Track(stream)
 
272
        track2 = Track(stream)
 
273
 
 
274
        timeline = Timeline()
 
275
 
 
276
        timeline.addTrack(track1)
 
277
        self.failUnlessRaises(TimelineError, timeline.addTrack, track1)
 
278
 
 
279
        timeline.addTrack(track2)
 
280
 
 
281
        timeline.removeTrack(track1)
 
282
        self.failUnlessRaises(TimelineError, timeline.removeTrack, track1)
 
283
 
 
284
        timeline.removeTrack(track2)
 
285
 
 
286
 
 
287
class TestTimelineAddRemoveTimelineObjects(TestCase):
 
288
    def testAddRemoveTimelineObjects(self):
 
289
        source_factory = StubFactory()
 
290
        stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
291
        source_factory.addOutputStream(stream)
 
292
        timeline = Timeline()
 
293
        track = Track(stream)
 
294
 
 
295
        track_object1 = SourceTrackObject(source_factory, stream)
 
296
        track_object2 = SourceTrackObject(source_factory, stream)
 
297
        track.addTrackObject(track_object1)
 
298
        track.addTrackObject(track_object2)
 
299
 
 
300
        timeline_object1 = TimelineObject(source_factory)
 
301
        timeline_object2 = TimelineObject(source_factory)
 
302
 
 
303
        self.failUnlessRaises(TimelineError,
 
304
                timeline.addTimelineObject, timeline_object1)
 
305
 
 
306
        timeline_object1.addTrackObject(track_object1)
 
307
        timeline.addTimelineObject(timeline_object1)
 
308
 
 
309
        self.failUnlessRaises(TimelineError,
 
310
                timeline.addTimelineObject, timeline_object1)
 
311
 
 
312
        timeline_object2.addTrackObject(track_object2)
 
313
        timeline.addTimelineObject(timeline_object2)
 
314
 
 
315
        timeline.removeTimelineObject(timeline_object1)
 
316
        self.failUnlessRaises(TimelineError,
 
317
                timeline.removeTimelineObject, timeline_object1)
 
318
 
 
319
        timeline.removeTimelineObject(timeline_object2)
 
320
 
 
321
    def testRemoveFactory(self):
 
322
        source_factory = StubFactory()
 
323
        stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
324
        source_factory.addOutputStream(stream)
 
325
        track = Track(stream)
 
326
        track_object1 = SourceTrackObject(source_factory, stream)
 
327
        track.addTrackObject(track_object1)
 
328
        track_object2 = SourceTrackObject(source_factory, stream)
 
329
        track.addTrackObject(track_object2)
 
330
        track_object3 = SourceTrackObject(source_factory, stream)
 
331
        track.addTrackObject(track_object3)
 
332
        timeline_object1 = TimelineObject(source_factory)
 
333
        timeline_object1.addTrackObject(track_object1)
 
334
        timeline_object2 = TimelineObject(source_factory)
 
335
        timeline_object2.addTrackObject(track_object2)
 
336
        timeline_object3 = TimelineObject(source_factory)
 
337
        timeline_object3.addTrackObject(track_object3)
 
338
        timeline = Timeline()
 
339
        timeline.addTrack(track)
 
340
        timeline.addTimelineObject(timeline_object1)
 
341
        timeline.addTimelineObject(timeline_object2)
 
342
        timeline.addTimelineObject(timeline_object3)
 
343
 
 
344
        self.failUnlessEqual(len(timeline.timeline_objects), 3)
 
345
        timeline.removeFactory(source_factory)
 
346
        self.failUnlessEqual(len(timeline.timeline_objects), 0)
 
347
 
 
348
 
 
349
class TestTimelineAddRemoveEffectsTracks(TestCase):
 
350
    def testAddRemoveEffectTracks(self):
 
351
        stream = VideoStream(gst.Caps("video/x-raw-rgb"))
 
352
        source_factory = StubFactory()
 
353
        source_factory.addOutputStream(stream)
 
354
        effect_factory = FakeEffectFactory()
 
355
        effect_factory.addInputStream(stream)
 
356
        effect_factory.addOutputStream(stream)
 
357
        timeline = Timeline()
 
358
        track = Track(stream)
 
359
 
 
360
        track_effect1 = TrackEffect(effect_factory, stream)
 
361
        track_effect2 = TrackEffect(effect_factory, stream)
 
362
 
 
363
        track_object1 = SourceTrackObject(source_factory, stream)
 
364
        track.addTrackObject(track_object1)
 
365
        timeline_object1 = TimelineObject(source_factory)
 
366
        timeline_object1.addTrackObject(track_object1)
 
367
        timeline.addTimelineObject(timeline_object1)
 
368
 
 
369
        track.addTrackObject(track_effect1)
 
370
        timeline_object1.addTrackObject(track_effect1)
 
371
        self.failUnlessRaises(TimelineError,
 
372
                timeline_object1.addTrackObject, track_effect1)
 
373
        track.addTrackObject(track_effect2)
 
374
        timeline_object1.addTrackObject(track_effect2)
 
375
        self.failUnlessRaises(TimelineError,
 
376
                timeline_object1.addTrackObject, track_effect2)
 
377
 
 
378
        timeline_object1.removeTrackObject(track_effect1)
 
379
        self.failUnlessRaises(TimelineError,
 
380
                timeline_object1.removeTrackObject, track_effect1)
 
381
        timeline_object1.removeTrackObject(track_effect2)
 
382
        self.failUnlessRaises(TimelineError,
 
383
                timeline_object1.removeTrackObject, track_effect2)
 
384
 
 
385
        track.removeTrackObject(track_effect1)
 
386
        track.removeTrackObject(track_effect2)
 
387
        timeline.removeTimelineObject(timeline_object1)
 
388
 
 
389
    def testRemoveEffectFactory(self):
 
390
        effect_factory = FakeEffectFactory()
 
391
        stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
392
        effect_factory.addInputStream(stream)
 
393
        effect_factory.addOutputStream(stream)
 
394
        track = Track(stream)
 
395
        track_effect1 = TrackEffect(effect_factory, stream)
 
396
        track.addTrackObject(track_effect1)
 
397
        track_effect2 = TrackEffect(effect_factory, stream)
 
398
        track.addTrackObject(track_effect2)
 
399
        track_effect3 = TrackEffect(effect_factory, stream)
 
400
        track.addTrackObject(track_effect3)
 
401
        timeline_object1 = TimelineObject(effect_factory)
 
402
        timeline_object1.addTrackObject(track_effect1)
 
403
        timeline_object1.addTrackObject(track_effect2)
 
404
        timeline_object1.addTrackObject(track_effect3)
 
405
        timeline = Timeline()
 
406
        timeline.addTrack(track)
 
407
        timeline.addTimelineObject(timeline_object1)
 
408
 
 
409
        self.failUnlessEqual(len(timeline_object1.track_objects), 3)
 
410
        self.failUnlessEqual(len(timeline.timeline_objects), 1)
 
411
        self.failUnlessEqual(len(track.track_objects), 3)
 
412
        timeline.removeFactory(effect_factory)
 
413
        self.failUnlessEqual(len(track.track_objects), 0)
 
414
        self.failUnlessEqual(len(timeline.timeline_objects), 0)
 
415
 
 
416
 
 
417
class TestTimeline(TestCase):
 
418
    def setUp(self):
 
419
        self.source_factory = StubFactory()
 
420
        self.stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
421
        self.source_factory.addOutputStream(self.stream)
 
422
        self.track1 = Track(self.stream)
 
423
        self.timeline = Timeline()
 
424
        TestCase.setUp(self)
 
425
 
 
426
    def tearDown(self):
 
427
        del self.source_factory
 
428
        del self.stream
 
429
        del self.track1
 
430
        del self.timeline
 
431
 
 
432
    def makeTimelineObject(self):
 
433
        track_object = SourceTrackObject(self.source_factory, self.stream)
 
434
        self.track1.addTrackObject(track_object)
 
435
        timeline_object = TimelineObject(self.source_factory)
 
436
        timeline_object.addTrackObject(track_object)
 
437
        self.timeline.addTimelineObject(timeline_object)
 
438
 
 
439
        return timeline_object
 
440
 
 
441
    def testGetPreviousTimelineObject(self):
 
442
        timeline_object1 = self.makeTimelineObject()
 
443
        timeline_object2 = self.makeTimelineObject()
 
444
        timeline_object3 = self.makeTimelineObject()
 
445
        timeline_object4 = self.makeTimelineObject()
 
446
 
 
447
        timeline_object1.start = 1 * gst.SECOND
 
448
        timeline_object1.duration = 5 * gst.SECOND
 
449
        timeline_object1.priority = 1
 
450
 
 
451
        timeline_object2.start = 8 * gst.SECOND
 
452
        timeline_object2.duration = 5 * gst.SECOND
 
453
        timeline_object2.priority = 1
 
454
 
 
455
        timeline_object3.start = 6 * gst.SECOND
 
456
        timeline_object3.duration = 5 * gst.SECOND
 
457
        timeline_object3.priority = 2
 
458
 
 
459
        timeline_object4.start = 7 * gst.SECOND
 
460
        timeline_object4.duration = 5 * gst.SECOND
 
461
        timeline_object4.priority = 3
 
462
 
 
463
        timeline = self.timeline
 
464
 
 
465
        # no previous track_objectect
 
466
        self.failUnlessRaises(TimelineError,
 
467
                timeline.getPreviousTimelineObject, timeline_object4)
 
468
 
 
469
        # same priority
 
470
        prev = timeline.getPreviousTimelineObject(timeline_object2)
 
471
        self.failUnlessEqual(prev, timeline_object1)
 
472
 
 
473
        # given priority
 
474
        prev = timeline.getPreviousTimelineObject(timeline_object2, priority=2)
 
475
        self.failUnlessEqual(prev, timeline_object3)
 
476
 
 
477
        # any priority
 
478
        prev = timeline.getPreviousTimelineObject(timeline_object2, priority=None)
 
479
        self.failUnlessEqual(prev, timeline_object4)
 
480
 
 
481
    def testGetPreviousTimelineObjectSameStart(self):
 
482
        timeline_object1 = self.makeTimelineObject()
 
483
        timeline_object2 = self.makeTimelineObject()
 
484
        timeline = self.timeline
 
485
 
 
486
        timeline_object1.start = 1 * gst.SECOND
 
487
        timeline_object1.duration = 5 * gst.SECOND
 
488
        timeline_object1.priority = 1
 
489
 
 
490
        timeline_object2.start = 1 * gst.SECOND
 
491
        timeline_object2.duration = 5 * gst.SECOND
 
492
        timeline_object2.priority = 2
 
493
 
 
494
        self.failUnlessRaises(TimelineError,
 
495
                timeline.getPreviousTimelineObject, timeline_object1)
 
496
        self.failUnlessRaises(TimelineError,
 
497
                timeline.getPreviousTimelineObject, timeline_object2)
 
498
 
 
499
        prev = timeline.getPreviousTimelineObject(timeline_object2, priority=None)
 
500
        self.failUnlessEqual(prev, timeline_object1)
 
501
 
 
502
        prev = timeline.getPreviousTimelineObject(timeline_object1, priority=None)
 
503
        self.failUnlessEqual(prev, timeline_object2)
 
504
 
 
505
    def testGetNextTrackObject(self):
 
506
        timeline_object1 = self.makeTimelineObject()
 
507
        timeline_object2 = self.makeTimelineObject()
 
508
        timeline_object3 = self.makeTimelineObject()
 
509
        timeline_object4 = self.makeTimelineObject()
 
510
 
 
511
        timeline_object1.start = 1 * gst.SECOND
 
512
        timeline_object1.duration = 5 * gst.SECOND
 
513
        timeline_object1.priority = 1
 
514
 
 
515
        timeline_object2.start = 8 * gst.SECOND
 
516
        timeline_object2.duration = 5 * gst.SECOND
 
517
        timeline_object2.priority = 1
 
518
 
 
519
        timeline_object3.start = 6 * gst.SECOND
 
520
        timeline_object3.duration = 5 * gst.SECOND
 
521
        timeline_object3.priority = 2
 
522
 
 
523
        timeline_object4.start = 7 * gst.SECOND
 
524
        timeline_object4.duration = 5 * gst.SECOND
 
525
        timeline_object4.priority = 3
 
526
 
 
527
        timeline = self.timeline
 
528
 
 
529
        # no next timeline_objectect
 
530
        self.failUnlessRaises(TimelineError, timeline.getNextTimelineObject, timeline_object2)
 
531
 
 
532
        # same priority
 
533
        prev = timeline.getNextTimelineObject(timeline_object1)
 
534
        self.failUnlessEqual(prev, timeline_object2)
 
535
 
 
536
        # given priority
 
537
        prev = timeline.getNextTimelineObject(timeline_object1, priority=2)
 
538
        self.failUnlessEqual(prev, timeline_object3)
 
539
 
 
540
        # any priority
 
541
        prev = timeline.getNextTimelineObject(timeline_object3, priority=None)
 
542
        self.failUnlessEqual(prev, timeline_object4)
 
543
 
 
544
    def testGetObjsAtTime(self):
 
545
        # we're going use this time as our test time
 
546
        time1 = 0
 
547
        time2 = 3 * gst.SECOND
 
548
        time3 = 6 * gst.SECOND
 
549
        time4 = 10 * gst.SECOND
 
550
 
 
551
        clip1 = self.makeTimelineObject()
 
552
        clip1.start = 2 * gst.SECOND
 
553
        clip1.duration = 5 * gst.SECOND
 
554
 
 
555
        # clip2 -- overlaps left edge of clip1
 
556
        clip2 = self.makeTimelineObject()
 
557
        clip2.start = 1 * gst.SECOND
 
558
        clip2.duration = 4 * gst.SECOND
 
559
 
 
560
        # clip 3 -- overlaps right edge of clip1
 
561
        clip3 = self.makeTimelineObject()
 
562
        clip3.start = long(2.5 * gst.SECOND)
 
563
        clip3.duration = 5 * gst.SECOND
 
564
 
 
565
        # clip 4 -- doesn't overlap at all
 
566
        clip4 = self.makeTimelineObject()
 
567
        clip4.start = 10 * gst.SECOND
 
568
        clip4.duration = 4 * gst.SECOND
 
569
 
 
570
        result = set(self.timeline.getObjsAtTime(time1))
 
571
        self.failUnlessEqual(result, set())
 
572
 
 
573
        result = set(self.timeline.getObjsAtTime(time2))
 
574
        self.failUnlessEqual(result, set((clip1, clip2, clip3)))
 
575
 
 
576
        result = set(self.timeline.getObjsAtTime(time3))
 
577
        self.failUnlessEqual(result, set((clip1, clip3)))
 
578
 
 
579
        result = set(self.timeline.getObjsAtTime(time4))
 
580
        self.failUnlessEqual(result, set())
 
581
 
 
582
    def testSplitSelection(self):
 
583
        # we're going use this time as our test time
 
584
        noclips = 7 * gst.SECOND
 
585
        oneclip = long(6.5 * gst.SECOND)
 
586
        threeclips = long(4.5 * gst.SECOND)
 
587
        fourclipsoneselected = long(2.5 * gst.SECOND)
 
588
 
 
589
        clip1 = self.makeTimelineObject()
 
590
        clip1.start = 2 * gst.SECOND
 
591
        clip1.duration = 5 * gst.SECOND
 
592
 
 
593
        clip2 = self.makeTimelineObject()
 
594
        clip2.start = 2 * gst.SECOND
 
595
        clip2.duration = 4 * gst.SECOND
 
596
 
 
597
        clip3 = self.makeTimelineObject()
 
598
        clip3.start = 2 * gst.SECOND
 
599
        clip3.duration = 3 * gst.SECOND
 
600
 
 
601
        clip4 = self.makeTimelineObject()
 
602
        clip4.start = 2 * gst.SECOND
 
603
        clip4.duration = 2 * gst.SECOND
 
604
 
 
605
        # test split no clips
 
606
        self.timeline.split(noclips)
 
607
        for i, clip in enumerate([clip1, clip2, clip3, clip4]):
 
608
            self.failUnlessEqual(clip.start, 2 * gst.SECOND)
 
609
            self.failUnlessEqual(clip.duration,
 
610
                (5 - i) * gst.SECOND)
 
611
 
 
612
        # test split one clip
 
613
        self.timeline.split(oneclip)
 
614
        self.failUnlessEqual(clip1.start, 2 * gst.SECOND)
 
615
        self.failUnlessEqual(clip1.duration, oneclip - 2 * gst.SECOND)
 
616
        for i, clip in enumerate([clip2, clip3, clip4]):
 
617
            self.failUnlessEqual(clip.start, 2 * gst.SECOND)
 
618
            self.failUnlessEqual(clip.duration,
 
619
                (5 - (i + 1)) * gst.SECOND)
 
620
 
 
621
        # test split three clips
 
622
        self.timeline.split(threeclips)
 
623
        for i, clip in enumerate([clip1, clip2, clip3]):
 
624
            self.failUnlessEqual(clip.start, 2 * gst.SECOND)
 
625
            self.failUnlessEqual(clip.start + clip.duration, threeclips)
 
626
        self.failUnlessEqual(clip4.start, 2 * gst.SECOND)
 
627
        self.failUnlessEqual(clip4.duration, 2 * gst.SECOND)
 
628
 
 
629
        # test split three clips, one selected
 
630
        self.timeline.selection.selected = set((clip4,))
 
631
        self.timeline.split(fourclipsoneselected)
 
632
        for i, clip in enumerate([clip1, clip2, clip3]):
 
633
            self.failUnlessEqual(clip.start, 2 * gst.SECOND)
 
634
            self.failUnlessEqual(clip.start + clip.duration, threeclips)
 
635
        self.failUnlessEqual(clip4.start, 2 * gst.SECOND)
 
636
        self.failUnlessEqual(clip4.duration + clip4.start,
 
637
            fourclipsoneselected)
 
638
 
 
639
    def testGetObjs(self):
 
640
        obj1 = self.makeTimelineObject()
 
641
        obj2 = self.makeTimelineObject()
 
642
        obj3 = self.makeTimelineObject()
 
643
        obj4 = self.makeTimelineObject()
 
644
 
 
645
        obj1.start = 0 * gst.SECOND
 
646
        obj1.duration = 5 * gst.SECOND
 
647
        obj1.priority = 1
 
648
 
 
649
        obj2.start = 5 * gst.SECOND
 
650
        obj2.duration = 5 * gst.SECOND
 
651
        obj2.priority = 2
 
652
 
 
653
        obj3.start = 8 * gst.SECOND
 
654
        obj3.duration = 5 * gst.SECOND
 
655
        obj3.priority = 3
 
656
 
 
657
        obj4.start = 15 * gst.SECOND
 
658
        obj4.duration = 5 * gst.SECOND
 
659
        obj4.priority = 4
 
660
 
 
661
        timeline = self.timeline
 
662
 
 
663
        time1 = 0 * gst.SECOND
 
664
        time2 = 5 * gst.SECOND
 
665
        time3 = 9 * gst.SECOND
 
666
        time4 = 14 * gst.SECOND
 
667
        tmp_obj_list = []
 
668
 
 
669
        # Objects before time.
 
670
        tmp_obj_list = []
 
671
        result = timeline.getObjsBeforeTime(time1)
 
672
        self.failUnlessEqual(result, tmp_obj_list)
 
673
        tmp_obj_list = [obj1]
 
674
        result = timeline.getObjsBeforeTime(time2)
 
675
        self.failUnlessEqual(result, tmp_obj_list)
 
676
        tmp_obj_list = [obj1]
 
677
        result = timeline.getObjsBeforeTime(time3)
 
678
        self.failUnlessEqual(result, tmp_obj_list)
 
679
        tmp_obj_list = [obj1, obj2, obj3]
 
680
        result = timeline.getObjsBeforeTime(time4)
 
681
        self.failUnlessEqual(result, tmp_obj_list)
 
682
 
 
683
        # Objects after time.
 
684
        tmp_obj_list = [obj1, obj2, obj3, obj4]
 
685
        result = timeline.getObjsAfterTime(time1)
 
686
        self.failUnlessEqual(result, tmp_obj_list)
 
687
        tmp_obj_list = [obj2, obj3, obj4]
 
688
        result = timeline.getObjsAfterTime(time2)
 
689
        self.failUnlessEqual(result, tmp_obj_list)
 
690
        tmp_obj_list = [obj4]
 
691
        result = timeline.getObjsAfterTime(time3)
 
692
        self.failUnlessEqual(result, tmp_obj_list)
 
693
        tmp_obj_list = [obj4]
 
694
        result = timeline.getObjsAfterTime(time4)
 
695
        self.failUnlessEqual(result, tmp_obj_list)
 
696
 
 
697
        # Objects at time.
 
698
        tmp_obj_list = []
 
699
        result = timeline.getObjsAtTime(time1)
 
700
        self.failUnlessEqual(result, tmp_obj_list)
 
701
        tmp_obj_list = []
 
702
        result = timeline.getObjsAtTime(time2)
 
703
        self.failUnlessEqual(result, tmp_obj_list)
 
704
        tmp_obj_list = [obj2, obj3]
 
705
        result = timeline.getObjsAtTime(time3)
 
706
        self.failUnlessEqual(result, tmp_obj_list)
 
707
        tmp_obj_list = []
 
708
        result = timeline.getObjsAtTime(time4)
 
709
        self.failUnlessEqual(result, tmp_obj_list)
 
710
 
 
711
        # Objects in region.
 
712
        tmp_obj_list = [obj1]
 
713
        result = timeline.getObjsInRegion(time1, time2)
 
714
        self.failUnlessEqual(result, tmp_obj_list)
 
715
        tmp_obj_list = []
 
716
        result = timeline.getObjsInRegion(time3, time4)
 
717
        self.failUnlessEqual(result, tmp_obj_list)
 
718
        tmp_obj_list = [obj3]
 
719
        result = timeline.getObjsInRegion(time1, time4, \
 
720
            min_priority=3, max_priority=4)
 
721
        self.failUnlessEqual(result, tmp_obj_list)
 
722
 
 
723
    def testGetKeyframe(self):
 
724
        timeline_object0 = self.makeTimelineObject()
 
725
        timeline_object1 = self.makeTimelineObject()
 
726
        timeline_object3 = self.makeTimelineObject()
 
727
 
 
728
        timeline_object0.start = 0 * gst.SECOND
 
729
        timeline_object0.duration = 1 * gst.SECOND
 
730
        timeline_object0.priority = 0
 
731
 
 
732
        timeline_object1.start = 1 * gst.SECOND
 
733
        timeline_object1.duration = 5 * gst.SECOND
 
734
        timeline_object1.priority = 1
 
735
 
 
736
        timeline_object3.start = 15 * gst.SECOND
 
737
        timeline_object3.duration = 5 * gst.SECOND
 
738
        timeline_object3.priority = 2
 
739
 
 
740
        factory = AudioTestSourceFactory()
 
741
        stream = AudioStream(gst.Caps("audio/x-raw-int"))
 
742
        track_object = SourceTrackObject(factory, stream)
 
743
        self.track1.addTrackObject(track_object)
 
744
        timeline_object2 = TimelineObject(factory)
 
745
        timeline_object2.addTrackObject(track_object)
 
746
        self.timeline.addTimelineObject(timeline_object2)
 
747
        timeline_object2.start = 3 * gst.SECOND
 
748
        timeline_object2.duration = 10 * gst.SECOND
 
749
        timeline_object2.priority = 1
 
750
 
 
751
        interpolator = track_object.getInterpolator("volume")
 
752
        keyframe_position = 7 * gst.SECOND - timeline_object2.start
 
753
        interpolator.newKeyframe(keyframe_position, 0.0, "mode")
 
754
 
 
755
        timeline = self.timeline
 
756
 
 
757
        time1 = 0
 
758
        time2 = 0.5 * gst.SECOND
 
759
        time3 = 2 * gst.SECOND
 
760
        time4 = 6.5 * gst.SECOND
 
761
        time5 = 10 * gst.SECOND
 
762
        time6 = 14 * gst.SECOND
 
763
        time7 = 25 * gst.SECOND
 
764
 
 
765
        result = timeline.getPrevKeyframe(time1)
 
766
        self.failUnlessEqual(result, None)
 
767
        result = timeline.getPrevKeyframe(time2)
 
768
        self.failUnlessEqual(result, 0 * gst.SECOND)
 
769
        result = timeline.getPrevKeyframe(time3)
 
770
        self.failUnlessEqual(result, 1 * gst.SECOND)
 
771
        result = timeline.getPrevKeyframe(time4)
 
772
        self.failUnlessEqual(result, 6 * gst.SECOND)
 
773
        result = timeline.getPrevKeyframe(time5)
 
774
        self.failUnlessEqual(result, 7 * gst.SECOND)
 
775
        result = timeline.getPrevKeyframe(time6)
 
776
        self.failUnlessEqual(result, 13 * gst.SECOND)
 
777
        result = timeline.getPrevKeyframe(time7)
 
778
        self.failUnlessEqual(result, 20 * gst.SECOND)
 
779
 
 
780
        result = timeline.getNextKeyframe(time1)
 
781
        self.failUnlessEqual(result, 1 * gst.SECOND)
 
782
        result = timeline.getNextKeyframe(time2)
 
783
        self.failUnlessEqual(result, 1 * gst.SECOND)
 
784
        result = timeline.getNextKeyframe(time3)
 
785
        self.failUnlessEqual(result, 3 * gst.SECOND)
 
786
        result = timeline.getNextKeyframe(time4)
 
787
        self.failUnlessEqual(result, 7 * gst.SECOND)
 
788
        result = timeline.getNextKeyframe(time5)
 
789
        self.failUnlessEqual(result, 13 * gst.SECOND)
 
790
        result = timeline.getNextKeyframe(time6)
 
791
        self.failUnlessEqual(result, 15 * gst.SECOND)
 
792
        result = timeline.getNextKeyframe(time7)
 
793
        self.failUnlessEqual(result, None)
 
794
 
 
795
        other_object2 = timeline_object2.split(8 * gst.SECOND)
 
796
        timeline_object2.start = 5 * gst.SECOND
 
797
        other_object2.start = 7 * gst.SECOND
 
798
        time1 = 7 * gst.SECOND
 
799
        time2 = 10 * gst.SECOND
 
800
        result = timeline.getNextKeyframe(time1)
 
801
        self.failUnlessEqual(result, 9 * gst.SECOND)
 
802
        result = timeline.getNextKeyframe(time2)
 
803
        self.failUnlessEqual(result, 12 * gst.SECOND)
 
804
 
 
805
        position = 8.5 * gst.SECOND
 
806
        interpolator = other_object2.track_objects[0].getInterpolator("volume")
 
807
        interpolator.newKeyframe(position)
 
808
        result = timeline.getNextKeyframe(time2)
 
809
        self.failUnlessEqual(result, 10.5 * gst.SECOND)
 
810
 
 
811
 
 
812
class TestLink(TestCase):
 
813
 
 
814
    def test(self):
 
815
        pass
 
816
 
 
817
    def testAddRemoveTimelineObjects(self):
 
818
        source_factory = StubFactory()
 
819
        source_factory.addOutputStream(VideoStream(gst.Caps("video/x-raw-yuv")))
 
820
        timeline_object1 = TimelineObject(source_factory)
 
821
        timeline_object2 = TimelineObject(source_factory)
 
822
 
 
823
        link = Link()
 
824
        link.addTimelineObject(timeline_object1)
 
825
        self.failUnlessRaises(TimelineError,
 
826
                link.addTimelineObject, timeline_object1)
 
827
 
 
828
        link.addTimelineObject(timeline_object2)
 
829
 
 
830
        link.removeTimelineObject(timeline_object1)
 
831
        self.failUnlessRaises(TimelineError,
 
832
                link.removeTimelineObject, timeline_object1)
 
833
 
 
834
        link.removeTimelineObject(timeline_object2)
 
835
 
 
836
    def setUp(self):
 
837
        TestCase.setUp(self)
 
838
        self.source_factory = StubFactory()
 
839
        self.stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
840
        self.source_factory.addOutputStream(self.stream)
 
841
        self.track1 = Track(self.stream)
 
842
        self.track2 = Track(self.stream)
 
843
        self.track_object1 = SourceTrackObject(self.source_factory, self.stream)
 
844
        self.track_object2 = SourceTrackObject(self.source_factory, self.stream)
 
845
        self.track_object3 = SourceTrackObject(self.source_factory, self.stream)
 
846
        self.track1.addTrackObject(self.track_object1)
 
847
        self.track1.addTrackObject(self.track_object2)
 
848
        self.track2.addTrackObject(self.track_object3)
 
849
        self.timeline_object1 = TimelineObject(self.source_factory)
 
850
        self.timeline_object1.addTrackObject(self.track_object1)
 
851
        self.timeline_object2 = TimelineObject(self.source_factory)
 
852
        self.timeline_object2.addTrackObject(self.track_object2)
 
853
        self.timeline_object3 = TimelineObject(self.source_factory)
 
854
        self.timeline_object3.addTrackObject(self.track_object3)
 
855
 
 
856
    def tearDown(self):
 
857
        self.timeline_object3.removeTrackObject(self.track_object3)
 
858
        self.timeline_object2.removeTrackObject(self.track_object2)
 
859
        self.timeline_object1.removeTrackObject(self.track_object1)
 
860
        self.track1.removeTrackObject(self.track_object1)
 
861
        self.track1.removeTrackObject(self.track_object2)
 
862
        self.track2.removeTrackObject(self.track_object3)
 
863
        del self.timeline_object3
 
864
        del self.timeline_object2
 
865
        del self.timeline_object1
 
866
        del self.track_object1
 
867
        del self.track_object2
 
868
        del self.track_object3
 
869
        del self.track1
 
870
        del self.track2
 
871
        del self.stream
 
872
        del self.source_factory
 
873
        TestCase.tearDown(self)
 
874
 
 
875
    def testLinkAttribute(self):
 
876
        timeline_object1 = self.timeline_object1
 
877
        timeline_object2 = self.timeline_object2
 
878
        timeline_object3 = self.timeline_object3
 
879
 
 
880
        self.failUnlessEqual(timeline_object1.link, None)
 
881
        self.failUnlessEqual(timeline_object2.link, None)
 
882
        self.failUnlessEqual(timeline_object3.link, None)
 
883
 
 
884
        link = Link()
 
885
        link.addTimelineObject(timeline_object1)
 
886
        link.addTimelineObject(timeline_object2)
 
887
        link.addTimelineObject(timeline_object3)
 
888
 
 
889
        link2 = Link()
 
890
        self.failUnlessRaises(TimelineError,
 
891
                link2.addTimelineObject, timeline_object1)
 
892
 
 
893
        self.failIfEqual(timeline_object1.link, None)
 
894
        self.failIfEqual(timeline_object2.link, None)
 
895
        self.failIfEqual(timeline_object3.link, None)
 
896
 
 
897
        link.removeTimelineObject(timeline_object1)
 
898
        self.failUnlessEqual(timeline_object1.link, None)
 
899
 
 
900
        link.removeTimelineObject(timeline_object2)
 
901
        self.failUnlessEqual(timeline_object2.link, None)
 
902
 
 
903
        link.removeTimelineObject(timeline_object3)
 
904
        self.failUnlessEqual(timeline_object3.link, None)
 
905
 
 
906
    def testLinkJoin(self):
 
907
        timeline_object1 = self.timeline_object1
 
908
        timeline_object2 = self.timeline_object2
 
909
        timeline_object3 = self.timeline_object3
 
910
 
 
911
        link1 = Link()
 
912
        link1.addTimelineObject(timeline_object1)
 
913
        link1.addTimelineObject(timeline_object2)
 
914
 
 
915
        link2 = Link()
 
916
        link2.addTimelineObject(timeline_object3)
 
917
 
 
918
        self.failUnlessEqual(timeline_object1.link, link1)
 
919
        self.failUnlessEqual(timeline_object2.link, link1)
 
920
        self.failUnlessEqual(timeline_object3.link, link2)
 
921
 
 
922
        link3 = link1.join(link2)
 
923
        self.failUnlessEqual(timeline_object1.link, link3)
 
924
        self.failUnlessEqual(timeline_object2.link, link3)
 
925
        self.failUnlessEqual(timeline_object3.link, link3)
 
926
 
 
927
    def testChangeStart(self):
 
928
        source_factory = self.source_factory
 
929
        stream = self.stream
 
930
        track1 = self.track1
 
931
        track2 = self.track2
 
932
        track_object1 = self.track_object1
 
933
        track_object2 = self.track_object2
 
934
        track_object3 = self.track_object3
 
935
 
 
936
        timeline_object1 = self.timeline_object1
 
937
        timeline_object2 = self.timeline_object2
 
938
        timeline_object3 = self.timeline_object3
 
939
 
 
940
        link = Link()
 
941
        link.addTimelineObject(timeline_object1)
 
942
        link.addTimelineObject(timeline_object2)
 
943
 
 
944
        self.failUnlessEqual(timeline_object1.start, 0)
 
945
        self.failUnlessEqual(timeline_object2.start, 0)
 
946
 
 
947
        # move start forward
 
948
        start = 3 * gst.SECOND
 
949
        timeline_object1.start = start
 
950
        self.failUnlessEqual(timeline_object1.start, start)
 
951
        self.failUnlessEqual(timeline_object2.start, start)
 
952
 
 
953
        # move start back
 
954
        start = 2 * gst.SECOND
 
955
        timeline_object2.start = start
 
956
        self.failUnlessEqual(timeline_object1.start, start)
 
957
        self.failUnlessEqual(timeline_object2.start, start)
 
958
 
 
959
        # add a third object (on a different track)
 
960
        timeline_object3.start = 10 * gst.SECOND
 
961
        link.addTimelineObject(timeline_object3)
 
962
 
 
963
        # move start from 2 to 4, this should shift timeline_object3 from 10 to
 
964
        # 12
 
965
        start = 4 * gst.SECOND
 
966
        timeline_object2.start = start
 
967
        self.failUnlessEqual(timeline_object1.start, start)
 
968
        self.failUnlessEqual(timeline_object2.start, start)
 
969
        self.failUnlessEqual(timeline_object3.start, 12 * gst.SECOND)
 
970
 
 
971
        # try to move timeline_object3 5 seconds back (to 7s). It should
 
972
        # actually stop the move to 8s so that timeline_object1 and
 
973
        # timeline_object2 don't go < 0s.
 
974
        start = 7 * gst.SECOND
 
975
        timeline_object3.start = start
 
976
        self.failUnlessEqual(timeline_object1.start, 0)
 
977
        self.failUnlessEqual(timeline_object2.start, 0)
 
978
        self.failUnlessEqual(timeline_object3.start, 8 * gst.SECOND)
 
979
 
 
980
        # unlink timeline_object1 and move it back to start = 1
 
981
        link.removeTimelineObject(timeline_object1)
 
982
        timeline_object1.start = 1 * gst.SECOND
 
983
        self.failUnlessEqual(timeline_object1.start, 1 * gst.SECOND)
 
984
        self.failUnlessEqual(timeline_object2.start, 0)
 
985
        self.failUnlessEqual(timeline_object3.start, 8 * gst.SECOND)
 
986
 
 
987
 
 
988
class TestTimelineEdges(TestCase):
 
989
    def setUp(self):
 
990
        TestCase.setUp(self)
 
991
        self.timeline_edges = TimelineEdges()
 
992
 
 
993
    def testRemove(self):
 
994
        self.timeline_edges.addStartEnd(0, 2000)
 
995
        self.timeline_edges.removeStartEnd(0, 2000)
 
996
 
 
997
    def testRemoveNotExisting(self):
 
998
        self.failUnlessRaises(TimelineError,
 
999
                self.timeline_edges.removeStartEnd, 1, 2000)
 
1000
 
 
1001
        self.timeline_edges.addStartEnd(0, 2000)
 
1002
        self.failUnlessRaises(TimelineError,
 
1003
                self.timeline_edges.removeStartEnd, 1, 2000)
 
1004
        self.failUnlessRaises(TimelineError,
 
1005
                self.timeline_edges.removeStartEnd, 0, 2001)
 
1006
 
 
1007
    def testNoEdges(self):
 
1008
        self.failUnlessEqual(self.timeline_edges.snapToEdge(500, 1000), (500, 0))
 
1009
 
 
1010
    def testSimple(self):
 
1011
        self.timeline_edges.addStartEnd(0, 2000)
 
1012
        self.failUnlessEqual(self.timeline_edges.snapToEdge(500, 1000), (0, 500))
 
1013
 
 
1014
        self.timeline_edges.removeStartEnd(0, 2000)
 
1015
        self.failUnlessEqual(self.timeline_edges.snapToEdge(500, 1000), (500, 0))
 
1016
 
 
1017
    def testSamePosition(self):
 
1018
        self.timeline_edges.addStartEnd(0, 2000)
 
1019
        self.timeline_edges.addStartEnd(0, 2000)
 
1020
 
 
1021
        self.failUnlessEqual(self.timeline_edges.snapToEdge(500, 1000), (0, 500))
 
1022
 
 
1023
        self.timeline_edges.removeStartEnd(0, 2000)
 
1024
 
 
1025
        self.failUnlessEqual(self.timeline_edges.snapToEdge(500, 1000), (0, 500))
 
1026
 
 
1027
        self.timeline_edges.removeStartEnd(0, 2000)
 
1028
 
 
1029
        self.failUnlessEqual(self.timeline_edges.snapToEdge(500, 1000), (500, 0))
 
1030
 
 
1031
    def testSnapStart(self):
 
1032
        self.timeline_edges = TimelineEdges()
 
1033
 
 
1034
        self.timeline_edges.addStartEnd(1000, 2000)
 
1035
 
 
1036
        # match start-left
 
1037
        self.failUnlessEqual(self.timeline_edges.snapToEdge(900, 1400), (1000, 100))
 
1038
 
 
1039
        # match start
 
1040
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1000, 1999), (1000, 0))
 
1041
 
 
1042
        # match start-right
 
1043
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1200, 1400), (1000, 200))
 
1044
 
 
1045
        # match end-left
 
1046
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1600, 1999), (1601, 1))
 
1047
 
 
1048
        # match end
 
1049
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1001, 2000), (1001, 0))
 
1050
 
 
1051
        # match end-right
 
1052
        self.failUnlessEqual(self.timeline_edges.snapToEdge(2100, 3000), (2000, 100))
 
1053
 
 
1054
        # match both start and end, start is returned
 
1055
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1000, 2000), (1000, 0))
 
1056
 
 
1057
    def testSnapDuration(self):
 
1058
        self.timeline_edges.addStartEnd(1000, 2000)
 
1059
 
 
1060
        # match start-left
 
1061
        self.failUnlessEqual(self.timeline_edges.snapToEdge(900), (1000, 100))
 
1062
 
 
1063
        # match start
 
1064
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1000), (1000, 0))
 
1065
 
 
1066
        # match start-right
 
1067
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1200), (1000, 200))
 
1068
 
 
1069
        # match end-left
 
1070
        self.failUnlessEqual(self.timeline_edges.snapToEdge(1999), (2000, 1))
 
1071
 
 
1072
        # match end
 
1073
        self.failUnlessEqual(self.timeline_edges.snapToEdge(2000), (2000, 0))
 
1074
 
 
1075
        # match end-right
 
1076
        self.failUnlessEqual(self.timeline_edges.snapToEdge(3000), (2000, 1000))
 
1077
 
 
1078
    def testAdjacenctObjs(self):
 
1079
        source_factory = FakeSourceFactory()
 
1080
        stream = AudioStream(gst.Caps("meh"))
 
1081
        track_object1 = SourceTrackObject(source_factory, stream)
 
1082
        track_object2 = SourceTrackObject(source_factory, stream)
 
1083
        track_object1.start = 500
 
1084
        track_object1.duration = 500
 
1085
        track_object2.start = 1000
 
1086
        track_object2.duration = 500
 
1087
        self.timeline_edges.addTrackObject(track_object1)
 
1088
        self.timeline_edges.addTrackObject(track_object2)
 
1089
        self.assertEquals(self.timeline_edges.getObjsIncidentOnTime(1000),
 
1090
            [track_object1, track_object2])
 
1091
        self.assertEquals(self.timeline_edges.getObjsAdjacentToStart(track_object2),
 
1092
            [track_object1])
 
1093
        self.assertEquals(self.timeline_edges.getObjsAdjacentToEnd(track_object1),
 
1094
            [track_object2])
 
1095
 
 
1096
        self.timeline_edges.removeTrackObject(track_object2)
 
1097
        self.assertEquals(self.timeline_edges.getObjsIncidentOnTime(1000),
 
1098
                [track_object1])
 
1099
 
 
1100
        self.timeline_edges.removeTrackObject(track_object1)
 
1101
        self.assertEquals(self.timeline_edges.getObjsIncidentOnTime(1000), [])
 
1102
 
 
1103
        track_object1.release()
 
1104
        track_object2.release()
 
1105
        del source_factory
 
1106
 
 
1107
 
 
1108
class TestTimelineAddFactory(TestCase):
 
1109
    def setUp(self):
 
1110
        TestCase.setUp(self)
 
1111
        self.audio_stream1 = AudioStream(gst.Caps('audio/x-raw-int'))
 
1112
        self.audio_stream2 = AudioStream(gst.Caps('audio/x-raw-int'))
 
1113
        self.audio_stream3 = AudioStream(gst.Caps('audio/x-raw-int'))
 
1114
        self.video_stream1 = VideoStream(gst.Caps('video/x-raw-rgb'))
 
1115
        self.video_stream2 = VideoStream(gst.Caps('video/x-raw-rgb'))
 
1116
        self.audio_track1 = Track(self.audio_stream1)
 
1117
        self.audio_track2 = Track(self.audio_stream2)
 
1118
        self.video_track1 = Track(self.video_stream1)
 
1119
        self.video_track2 = Track(self.video_stream2)
 
1120
        self.timeline = Timeline()
 
1121
        self.timeline.addTrack(self.audio_track1)
 
1122
        self.timeline.addTrack(self.audio_track2)
 
1123
        self.timeline.addTrack(self.video_track1)
 
1124
        self.timeline.addTrack(self.video_track2)
 
1125
 
 
1126
        self.source_factory = StubFactory()
 
1127
        self.effect_factory = FakeEffectFactory()
 
1128
 
 
1129
    def tearDown(self):
 
1130
        del self.audio_stream1
 
1131
        del self.audio_stream2
 
1132
        del self.audio_stream3
 
1133
        del self.video_stream1
 
1134
        del self.video_stream2
 
1135
        del self.audio_track1
 
1136
        del self.audio_track2
 
1137
        del self.video_track1
 
1138
        del self.video_track2
 
1139
        del self.timeline
 
1140
        del self.source_factory
 
1141
        del self.effect_factory
 
1142
        TestCase.tearDown(self)
 
1143
 
 
1144
    def testNoStreams(self):
 
1145
        self.failUnlessRaises(TimelineError, self.timeline.addSourceFactory, self.source_factory)
 
1146
 
 
1147
    def testAudioOnly(self):
 
1148
        self.source_factory.addOutputStream(self.audio_stream1)
 
1149
        self.timeline.addSourceFactory(self.source_factory)
 
1150
        self.failUnlessEqual(len(self.audio_track1.track_objects), 1)
 
1151
        self.failUnlessEqual(len(self.audio_track2.track_objects), 0)
 
1152
        self.failUnlessEqual(len(self.video_track1.track_objects), 0)
 
1153
        self.failUnlessEqual(len(self.video_track2.track_objects), 0)
 
1154
 
 
1155
    def testVideoOnly(self):
 
1156
        self.source_factory.addOutputStream(self.video_stream1)
 
1157
        self.timeline.addSourceFactory(self.source_factory)
 
1158
        self.failUnlessEqual(len(self.audio_track1.track_objects), 0)
 
1159
        self.failUnlessEqual(len(self.audio_track2.track_objects), 0)
 
1160
        self.failUnlessEqual(len(self.video_track1.track_objects), 1)
 
1161
        self.failUnlessEqual(len(self.video_track2.track_objects), 0)
 
1162
 
 
1163
    def testVideoStreamVideoEffect(self):
 
1164
        self.source_factory.addOutputStream(self.video_stream1)
 
1165
        self.timeline.addSourceFactory(self.source_factory)
 
1166
        self.effect_factory.addInputStream(self.video_stream1)
 
1167
        self.effect_factory.addOutputStream(self.video_stream2)
 
1168
        self.timeline.addEffectFactoryOnObject(self.effect_factory, self.timeline.timeline_objects)
 
1169
        self.failUnlessEqual(len(self.audio_track1.track_objects), 0)
 
1170
        self.failUnlessEqual(len(self.audio_track2.track_objects), 0)
 
1171
        self.failUnlessEqual(len(self.video_track1.track_objects), 2)
 
1172
        self.failUnlessEqual(len(self.video_track2.track_objects), 0)
 
1173
 
 
1174
    def testAudioStreamAudioEffect(self):
 
1175
        self.source_factory.addOutputStream(self.audio_stream1)
 
1176
        self.timeline.addSourceFactory(self.source_factory)
 
1177
        self.effect_factory.addInputStream(self.audio_stream1)
 
1178
        self.effect_factory.addOutputStream(self.audio_stream2)
 
1179
        self.timeline.addEffectFactoryOnObject(self.effect_factory, self.timeline.timeline_objects)
 
1180
        self.failUnlessEqual(len(self.audio_track1.track_objects), 2)
 
1181
        self.failUnlessEqual(len(self.audio_track2.track_objects), 0)
 
1182
        self.failUnlessEqual(len(self.video_track1.track_objects), 0)
 
1183
        self.failUnlessEqual(len(self.video_track2.track_objects), 0)
 
1184
 
 
1185
    def test1Audio1Video(self):
 
1186
        self.source_factory.addOutputStream(self.audio_stream1)
 
1187
        self.source_factory.addOutputStream(self.video_stream1)
 
1188
        self.timeline.addSourceFactory(self.source_factory)
 
1189
        self.failUnlessEqual(len(self.audio_track1.track_objects), 1)
 
1190
        self.failUnlessEqual(len(self.audio_track2.track_objects), 0)
 
1191
        self.failUnlessEqual(len(self.video_track1.track_objects), 1)
 
1192
        self.failUnlessEqual(len(self.video_track2.track_objects), 0)
 
1193
 
 
1194
    def testConflictNotEnoughTracks(self):
 
1195
        # 3 audio streams, only 2 audio tracks in the timeline
 
1196
        self.source_factory.addOutputStream(self.audio_stream1)
 
1197
        self.source_factory.addOutputStream(self.audio_stream2)
 
1198
        self.source_factory.addOutputStream(self.audio_stream3)
 
1199
        self.failUnlessRaises(TimelineError, self.timeline.addSourceFactory,
 
1200
                self.source_factory, strict=True)
 
1201
        self.failUnlessEqual(len(self.audio_track1.track_objects), 0)
 
1202
        self.failUnlessEqual(len(self.audio_track2.track_objects), 0)
 
1203
        self.failUnlessEqual(len(self.video_track1.track_objects), 0)
 
1204
        self.failUnlessEqual(len(self.video_track2.track_objects), 0)
 
1205
 
 
1206
 
 
1207
class TestContexts(TestCase):
 
1208
 
 
1209
    def setUp(self):
 
1210
        TestCase.setUp(self)
 
1211
        self.timeline = Timeline()
 
1212
        self.source_factory = StubFactory()
 
1213
        self.stream = AudioStream(gst.Caps('audio/x-raw-int'))
 
1214
        self.source_factory.addOutputStream(self.stream)
 
1215
        self.track1 = Track(self.stream)
 
1216
        self.track2 = Track(self.stream)
 
1217
        self.track_object1 = SourceTrackObject(self.source_factory, self.stream)
 
1218
        self.track_object2 = SourceTrackObject(self.source_factory, self.stream)
 
1219
        self.track_object3 = SourceTrackObject(self.source_factory, self.stream)
 
1220
        self.track1.addTrackObject(self.track_object1)
 
1221
        self.track1.addTrackObject(self.track_object2)
 
1222
        self.track2.addTrackObject(self.track_object3)
 
1223
        self.timeline_object1 = TimelineObject(self.source_factory)
 
1224
        self.timeline_object1.addTrackObject(self.track_object1)
 
1225
        self.timeline_object2 = TimelineObject(self.source_factory)
 
1226
        self.timeline_object2.addTrackObject(self.track_object2)
 
1227
        self.timeline_object3 = TimelineObject(self.source_factory)
 
1228
        self.timeline_object3.addTrackObject(self.track_object3)
 
1229
        self.timeline.addTimelineObject(self.timeline_object1)
 
1230
        self.timeline.addTimelineObject(self.timeline_object2)
 
1231
        self.timeline.addTimelineObject(self.timeline_object3)
 
1232
        self.other = set([self.track_object2, self.track_object3])
 
1233
 
 
1234
    def testMoveContext(self):
 
1235
        # set up the initial state of the timeline and create the track object
 
1236
        # [focus]     [t2   ]     [t3     ]
 
1237
        self.track_object1.start = 0
 
1238
        self.track_object1.duration = gst.SECOND * 5
 
1239
        self.track_object2.start = 15 * gst.SECOND
 
1240
        self.track_object3.start = 25 * gst.SECOND
 
1241
        context = MoveContext(self.timeline, self.track_object1, set())
 
1242
 
 
1243
        # make an edit, check that the edit worked as expected
 
1244
        #    [focus]  [t2   ]     [t3     ]
 
1245
        context.editTo(gst.SECOND * 10, 0)
 
1246
        self.failUnlessEqual(self.track_object1.start, gst.SECOND * 10)
 
1247
        self.failUnlessEqual(self.track_object1.duration, gst.SECOND * 5)
 
1248
        self.failUnlessEqual(self.track_object1.in_point, 0)
 
1249
        self.failUnlessEqual(self.track_object2.start, gst.SECOND * 15)
 
1250
        self.failUnlessEqual(self.track_object3.start, gst.SECOND * 25)
 
1251
 
 
1252
        # change to the ripple mode, check that the edit worked as expected
 
1253
        #            [focus]  [t2   ]     [t3     ]
 
1254
        context.setMode(context.RIPPLE)
 
1255
        context.editTo(gst.SECOND * 20, 0)
 
1256
        self.failUnlessEqual(self.track_object1.start, gst.SECOND * 20)
 
1257
        self.failUnlessEqual(self.track_object1.duration, gst.SECOND * 5)
 
1258
        self.failUnlessEqual(self.track_object1.in_point, 0)
 
1259
        self.failUnlessEqual(self.track_object2.start, gst.SECOND * 35)
 
1260
        self.failUnlessEqual(self.track_object3.start, gst.SECOND * 45)
 
1261
 
 
1262
        # change back to default mode, and make sure this works as expected
 
1263
        #             [t2   ]     [t3     ]
 
1264
        #            [focus]
 
1265
        context.setMode(context.DEFAULT)
 
1266
        self.failUnlessEqual(self.track_object1.start, gst.SECOND * 20)
 
1267
        self.failUnlessEqual(self.track_object1.duration, gst.SECOND * 5)
 
1268
        self.failUnlessEqual(self.track_object1.in_point, 0)
 
1269
        self.failUnlessEqual(self.track_object2.start, gst.SECOND * 15)
 
1270
        self.failUnlessEqual(self.track_object3.start, gst.SECOND * 25)
 
1271
        context.finish()
 
1272
 
 
1273
    def testMoveContextOverlapDifferentTracks(self):
 
1274
        # start
 
1275
        # track1:          [focus][t2]
 
1276
        # track2:  [t3 ]
 
1277
        self.track_object1.start = 20 * gst.SECOND
 
1278
        self.track_object1.duration = 10 * gst.SECOND
 
1279
        self.track_object1.priority = 1
 
1280
        self.track_object2.start = 30 * gst.SECOND
 
1281
        self.track_object2.duration = 10 * gst.SECOND
 
1282
        self.track_object2.priority = 1
 
1283
        self.track_object3.start = 1 * gst.SECOND
 
1284
        self.track_object3.duration = 10 * gst.SECOND
 
1285
        self.track_object3.priority = 1
 
1286
 
 
1287
        # move to
 
1288
        # track1:     [focus][t2]
 
1289
        # track2:  [t3 ]
 
1290
        context = MoveContext(self.timeline, self.track_object1,
 
1291
                set([self.track_object2]))
 
1292
        context.editTo(gst.SECOND * 1, 0)
 
1293
        context.finish()
 
1294
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1295
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1296
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1297
        self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
 
1298
        self.failUnlessEqual(self.track_object3.start, 1 * gst.SECOND)
 
1299
        self.failUnlessEqual(self.track_object3.duration, 10 * gst.SECOND)
 
1300
 
 
1301
        # move to
 
1302
        # track1:     [focus][t2]
 
1303
        # track2:             [t3 ]
 
1304
        context = MoveContext(self.timeline, self.track_object3,
 
1305
                set([]))
 
1306
        context.editTo(gst.SECOND * 10, 0)
 
1307
        context.finish()
 
1308
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1309
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1310
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1311
        self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
 
1312
        self.failUnlessEqual(self.track_object3.start, 10 * gst.SECOND)
 
1313
        self.failUnlessEqual(self.track_object3.duration, 10 * gst.SECOND)
 
1314
 
 
1315
    def testMoveContextOverlapTransition(self):
 
1316
        # start
 
1317
        # track1:  [focus  ][  t2  ]
 
1318
        # track2:  [t3 ]
 
1319
        self.track_object1.start = 0 * gst.SECOND
 
1320
        self.track_object1.duration = 10 * gst.SECOND
 
1321
        self.track_object1.priority = 1
 
1322
        self.track_object2.start = 10 * gst.SECOND
 
1323
        self.track_object2.duration = 10 * gst.SECOND
 
1324
        self.track_object2.priority = 1
 
1325
        self.track_object3.start = 0 * gst.SECOND
 
1326
        self.track_object3.duration = 10 * gst.SECOND
 
1327
        self.track_object3.priority = 1
 
1328
 
 
1329
        # move to
 
1330
        # track1:  [focus[  ]t2  ]
 
1331
        # track2:  [t3 ]
 
1332
        context = MoveContext(self.timeline, self.track_object2, set([]))
 
1333
        context.editTo(gst.SECOND * 5, 1)
 
1334
        context.finish()
 
1335
        self.failUnlessEqual(self.track_object1.start, 0 * gst.SECOND)
 
1336
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1337
        self.failUnlessEqual(self.track_object2.start, 5 * gst.SECOND)
 
1338
        self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
 
1339
        self.failUnlessEqual(self.track_object3.start, 0 * gst.SECOND)
 
1340
        self.failUnlessEqual(self.track_object3.duration, 10 * gst.SECOND)
 
1341
 
 
1342
    def testMoveContextFocusNotEarliest(self):
 
1343
        #     [t2  ][focus]  [t3     ]
 
1344
        self.track_object1.start = 10 * gst.SECOND
 
1345
        self.track_object1.duration = 5 * gst.SECOND
 
1346
        self.track_object2.start = 1 * gst.SECOND
 
1347
        self.track_object2.duration = 9 * gst.SECOND
 
1348
        self.track_object3.start = 15 * gst.SECOND
 
1349
        self.track_object3.duration = 10 * gst.SECOND
 
1350
        self.track_object3.priority = 1
 
1351
        other = set([self.track_object2])
 
1352
 
 
1353
        context = MoveContext(self.timeline, self.track_object1, other)
 
1354
        context.editTo(20 * gst.SECOND, 0)
 
1355
 
 
1356
        #                           [t2  ][focus]
 
1357
        #                    [t3     ]
 
1358
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1359
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1360
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1361
 
 
1362
        context.setMode(context.RIPPLE)
 
1363
 
 
1364
        #                            [t2  ][focus]  [t3     ]
 
1365
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1366
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1367
        self.failUnlessEqual(self.track_object3.start, 25 * gst.SECOND)
 
1368
 
 
1369
        context.setMode(context.DEFAULT)
 
1370
 
 
1371
        #                           [t2  ][focus]
 
1372
        #                    [t3     ]
 
1373
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1374
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1375
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1376
 
 
1377
        context.finish()
 
1378
 
 
1379
    def testMoveContextMargins(self):
 
1380
        self.other = set([self.track_object3])
 
1381
 
 
1382
        self.track_object1.start = 16 * gst.SECOND
 
1383
        self.track_object1.duration = 10 * gst.SECOND
 
1384
 
 
1385
        self.track_object2.start = 10 * gst.SECOND
 
1386
        self.track_object2.duration = 5 * gst.SECOND
 
1387
 
 
1388
        self.track_object3.start = 3 * gst.SECOND
 
1389
        self.track_object3.duration = 7 * gst.SECOND
 
1390
 
 
1391
        # move before left margin, should clamp
 
1392
        context = MoveContext(self.timeline, self.track_object1, self.other)
 
1393
        context.editTo(8 * gst.SECOND, 0)
 
1394
        context.finish()
 
1395
 
 
1396
        self.failUnlessEqual(self.track_object1.start, 15 * gst.SECOND)
 
1397
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1398
        self.failUnlessEqual(self.track_object3.start, 2 * gst.SECOND)
 
1399
 
 
1400
        # move back, no clamp
 
1401
        context = MoveContext(self.timeline, self.track_object1, self.other)
 
1402
        context.editTo(16 * gst.SECOND, 0)
 
1403
        context.finish()
 
1404
 
 
1405
        self.failUnlessEqual(self.track_object1.start, 16 * gst.SECOND)
 
1406
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1407
        self.failUnlessEqual(self.track_object3.start, 3 * gst.SECOND)
 
1408
 
 
1409
        # move past right margin, should clamp
 
1410
        context = MoveContext(self.timeline, self.track_object2, self.other)
 
1411
        context.editTo(20 * gst.SECOND, 0)
 
1412
        context.finish()
 
1413
 
 
1414
        self.failUnlessEqual(self.track_object1.start, 16 * gst.SECOND)
 
1415
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1416
        self.failUnlessEqual(self.track_object3.start, 4 * gst.SECOND)
 
1417
 
 
1418
    def testMoveContextMarginsPriorityChange(self):
 
1419
        self.other = set([self.track_object3])
 
1420
 
 
1421
        self.track_object1.start = 5 * gst.SECOND
 
1422
        self.track_object1.duration = 10 * gst.SECOND
 
1423
        self.track_object1.priority = 0
 
1424
 
 
1425
        self.track_object2.start = 5 * gst.SECOND
 
1426
        self.track_object2.duration = 10 * gst.SECOND
 
1427
        self.track_object2.priority = 1
 
1428
 
 
1429
        self.track_object3.start = 15 * gst.SECOND
 
1430
        self.track_object3.duration = 10 * gst.SECOND
 
1431
        self.track_object3.priority = 1
 
1432
 
 
1433
        # same start, priority bump
 
1434
        context = MoveContext(self.timeline, self.track_object2, self.other)
 
1435
        context.editTo(5 * gst.SECOND, 0)
 
1436
        context.finish()
 
1437
 
 
1438
        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
 
1439
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1440
        self.failUnlessEqual(self.track_object2.start, 5 * gst.SECOND)
 
1441
        self.failUnlessEqual(self.track_object2.priority, 1)
 
1442
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1443
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1444
 
 
1445
        # collapse left
 
1446
        self.track_object2.start = 4 * gst.SECOND
 
1447
        self.track_object2.duration = 10 * gst.SECOND
 
1448
        self.track_object2.priority = 1
 
1449
 
 
1450
        context = MoveContext(self.timeline, self.track_object2, self.other)
 
1451
        context.editTo(4 * gst.SECOND, 0)
 
1452
        context.finish()
 
1453
 
 
1454
        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
 
1455
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1456
        self.failUnlessEqual(self.track_object2.start, 4 * gst.SECOND)
 
1457
        self.failUnlessEqual(self.track_object2.priority, 1)
 
1458
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1459
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1460
 
 
1461
        # collapse right
 
1462
        self.track_object2.start = 6 * gst.SECOND
 
1463
        self.track_object2.duration = 10 * gst.SECOND
 
1464
        self.track_object2.priority = 1
 
1465
 
 
1466
        context = MoveContext(self.timeline, self.track_object2, self.other)
 
1467
        context.editTo(6 * gst.SECOND, 0)
 
1468
        context.finish()
 
1469
 
 
1470
        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
 
1471
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1472
        self.failUnlessEqual(self.track_object2.start, 6 * gst.SECOND)
 
1473
        self.failUnlessEqual(self.track_object2.priority, 1)
 
1474
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1475
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1476
 
 
1477
    def testMoveContextMarginsPriorityChangeMore(self):
 
1478
        self.other = set([self.track_object3])
 
1479
 
 
1480
        self.track_object1.start = 20 * gst.SECOND
 
1481
        self.track_object1.duration = 10 * gst.SECOND
 
1482
        self.track_object1.priority = 0
 
1483
 
 
1484
        self.track_object2.start = 10 * gst.SECOND
 
1485
        self.track_object2.duration = 10 * gst.SECOND
 
1486
        self.track_object2.priority = 1
 
1487
 
 
1488
        self.track_object3.start = 20 * gst.SECOND
 
1489
        self.track_object3.duration = 10 * gst.SECOND
 
1490
        self.track_object3.priority = 1
 
1491
 
 
1492
        # same start, priority bump
 
1493
        context = MoveContext(self.timeline, self.track_object2, self.other)
 
1494
        context.editTo(10 * gst.SECOND, 0)
 
1495
        context.finish()
 
1496
 
 
1497
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1498
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1499
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1500
        self.failUnlessEqual(self.track_object2.priority, 1)
 
1501
        self.failUnlessEqual(self.track_object3.start, 20 * gst.SECOND)
 
1502
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1503
 
 
1504
        # collapse left
 
1505
        self.track_object2.start = 9 * gst.SECOND
 
1506
        self.track_object2.duration = 10 * gst.SECOND
 
1507
        self.track_object2.priority = 1
 
1508
 
 
1509
        self.track_object3.start = 19 * gst.SECOND
 
1510
        self.track_object3.duration = 10 * gst.SECOND
 
1511
        self.track_object3.priority = 1
 
1512
 
 
1513
        context = MoveContext(self.timeline, self.track_object2, self.other)
 
1514
        context.editTo(9 * gst.SECOND, 0)
 
1515
        context.finish()
 
1516
 
 
1517
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1518
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1519
        self.failUnlessEqual(self.track_object2.start, 9 * gst.SECOND)
 
1520
        self.failUnlessEqual(self.track_object2.priority, 1)
 
1521
        self.failUnlessEqual(self.track_object3.start, 19 * gst.SECOND)
 
1522
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1523
 
 
1524
        # collapse right
 
1525
        self.track_object2.start = 21 * gst.SECOND
 
1526
        self.track_object2.duration = 10 * gst.SECOND
 
1527
        self.track_object2.priority = 1
 
1528
 
 
1529
        self.track_object3.start = 31 * gst.SECOND
 
1530
        self.track_object3.duration = 10 * gst.SECOND
 
1531
        self.track_object3.priority = 1
 
1532
 
 
1533
        context = MoveContext(self.timeline,
 
1534
                self.track_object3, set([self.track_object2]))
 
1535
        context.editTo(31 * gst.SECOND, 0)
 
1536
        context.finish()
 
1537
 
 
1538
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1539
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1540
        self.failUnlessEqual(self.track_object2.start, 21 * gst.SECOND)
 
1541
        self.failUnlessEqual(self.track_object2.priority, 1)
 
1542
        self.failUnlessEqual(self.track_object3.start, 31 * gst.SECOND)
 
1543
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1544
 
 
1545
    def testMoveContextMarginsZigZag(self):
 
1546
        self.track_object4 = SourceTrackObject(self.source_factory, self.stream)
 
1547
        self.track1.addTrackObject(self.track_object4)
 
1548
        self.timeline_object4 = TimelineObject(self.source_factory)
 
1549
        self.timeline_object4.addTrackObject(self.track_object4)
 
1550
        self.timeline.addTimelineObject(self.timeline_object4)
 
1551
 
 
1552
        self.track_object1.start = 0 * gst.SECOND
 
1553
        self.track_object1.duration = 10 * gst.SECOND
 
1554
        self.track_object1.priority = 0
 
1555
 
 
1556
        self.track_object2.start = 15 * gst.SECOND
 
1557
        self.track_object2.duration = 10 * gst.SECOND
 
1558
        self.track_object2.priority = 0
 
1559
 
 
1560
        self.track_object3.start = 10 * gst.SECOND
 
1561
        self.track_object3.duration = 10 * gst.SECOND
 
1562
        self.track_object3.priority = 1
 
1563
 
 
1564
        self.track_object4.start = 25 * gst.SECOND
 
1565
        self.track_object4.duration = 10 * gst.SECOND
 
1566
        self.track_object4.priority = 1
 
1567
 
 
1568
        context = MoveContext(self.timeline, self.track_object2,
 
1569
                set([self.track_object3]))
 
1570
        context.editTo(9 * gst.SECOND, 0)
 
1571
        context.finish()
 
1572
 
 
1573
        self.failUnlessEqual(self.track_object1.start, 0 * gst.SECOND)
 
1574
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1575
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1576
        self.failUnlessEqual(self.track_object2.priority, 0)
 
1577
        self.failUnlessEqual(self.track_object3.start, 5 * gst.SECOND)
 
1578
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1579
        self.failUnlessEqual(self.track_object4.start, 25 * gst.SECOND)
 
1580
        self.failUnlessEqual(self.track_object4.priority, 1)
 
1581
 
 
1582
        context = MoveContext(self.timeline, self.track_object2,
 
1583
                set([self.track_object3]))
 
1584
        context.editTo(25 * gst.SECOND, 0)
 
1585
        context.finish()
 
1586
 
 
1587
        self.failUnlessEqual(self.track_object1.start, 0 * gst.SECOND)
 
1588
        self.failUnlessEqual(self.track_object1.priority, 0)
 
1589
        self.failUnlessEqual(self.track_object2.start, 20 * gst.SECOND)
 
1590
        self.failUnlessEqual(self.track_object2.priority, 0)
 
1591
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1592
        self.failUnlessEqual(self.track_object3.priority, 1)
 
1593
        self.failUnlessEqual(self.track_object4.start, 25 * gst.SECOND)
 
1594
        self.failUnlessEqual(self.track_object4.priority, 1)
 
1595
 
 
1596
        del self.timeline_object4
 
1597
        del self.track_object4
 
1598
 
 
1599
    def testTrimStartContext(self):
 
1600
        self.track_object1.start = 1 * gst.SECOND
 
1601
        self.track_object1.in_point = 3 * gst.SECOND
 
1602
        self.track_object1.duration = 10 * gst.SECOND
 
1603
        self.track_object2.start = 11 * gst.SECOND
 
1604
        self.track_object2.in_point = 10 * gst.SECOND
 
1605
        self.track_object2.duration = 10 * gst.SECOND
 
1606
        self.track_object3.start = 25 * gst.SECOND
 
1607
        self.track_object3.in_point = 20 * gst.SECOND
 
1608
        self.track_object3.duration = 10 * gst.SECOND
 
1609
 
 
1610
        # set up the initial state of the timeline and create the track object
 
1611
        # [focus]     [t2   ]     [t3     ]
 
1612
        context = TrimStartContext(self.timeline, self.track_object1, self.other)
 
1613
        context.editTo(gst.SECOND * 5, 0)
 
1614
        context.finish()
 
1615
 
 
1616
        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
 
1617
        self.failUnlessEqual(self.track_object1.in_point, 7 * gst.SECOND)
 
1618
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1619
        self.failUnlessEqual(self.track_object2.in_point, 10 * gst.SECOND)
 
1620
        self.failUnlessEqual(self.track_object3.start, 25 * gst.SECOND)
 
1621
        self.failUnlessEqual(self.track_object3.in_point, 20 * gst.SECOND)
 
1622
 
 
1623
    def testTrimStartContextMargins(self):
 
1624
        self.track_object1.start = 1 * gst.SECOND
 
1625
        self.track_object1.in_point = 2 * gst.SECOND
 
1626
        self.track_object1.duration = 10 * gst.SECOND
 
1627
        self.track_object2.start = 12 * gst.SECOND
 
1628
        self.track_object2.in_point = 3 * gst.SECOND
 
1629
        self.track_object2.duration = 10 * gst.SECOND
 
1630
 
 
1631
        context = TrimStartContext(self.timeline, self.track_object2, self.other)
 
1632
        context.editTo(gst.SECOND * 9, 0)
 
1633
        context.finish()
 
1634
 
 
1635
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1636
        self.failUnlessEqual(self.track_object1.in_point, 2 * gst.SECOND)
 
1637
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1638
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1639
        self.failUnlessEqual(self.track_object2.in_point, 2 * gst.SECOND)
 
1640
        self.failUnlessEqual(self.track_object2.duration, 11 * gst.SECOND)
 
1641
 
 
1642
    def testTrimStartContextMarginsDifferentTracks(self):
 
1643
        # start
 
1644
        # track1:        [focus][t2]
 
1645
        # track2:  [t3 ]
 
1646
        self.track_object1.start = 20 * gst.SECOND
 
1647
        self.track_object1.in_point = 15 * gst.SECOND
 
1648
        self.track_object1.duration = 10 * gst.SECOND
 
1649
        self.track_object1.priority = 1
 
1650
        self.track_object2.start = 30 * gst.SECOND
 
1651
        self.track_object2.duration = 10 * gst.SECOND
 
1652
        self.track_object2.priority = 1
 
1653
        self.track_object3.start = 1 * gst.SECOND
 
1654
        self.track_object3.duration = 10 * gst.SECOND
 
1655
        self.track_object3.priority = 1
 
1656
 
 
1657
        # trim back to
 
1658
        # track1:    [     focus][t2]
 
1659
        # track2:  [t3 ]
 
1660
        context = TrimStartContext(self.timeline, self.track_object1, set([]))
 
1661
        context.editTo(gst.SECOND * 5, 0)
 
1662
        context.finish()
 
1663
        self.failUnlessEqual(self.track_object1.start, 5 * gst.SECOND)
 
1664
        self.failUnlessEqual(self.track_object1.duration, 25 * gst.SECOND)
 
1665
        self.failUnlessEqual(self.track_object2.start, 30 * gst.SECOND)
 
1666
        self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
 
1667
        self.failUnlessEqual(self.track_object3.start, 1 * gst.SECOND)
 
1668
        self.failUnlessEqual(self.track_object3.duration, 10 * gst.SECOND)
 
1669
 
 
1670
    def testTrimEndContext(self):
 
1671
        self.track_object1.start = 1 * gst.SECOND
 
1672
        self.track_object1.in_point = 3 * gst.SECOND
 
1673
        self.track_object1.duration = 15 * gst.SECOND
 
1674
        self.track_object2.start = 16 * gst.SECOND
 
1675
        self.track_object2.in_point = 10 * gst.SECOND
 
1676
        self.track_object2.duration = 16 * gst.SECOND
 
1677
        self.track_object3.start = 32 * gst.SECOND
 
1678
        self.track_object3.in_point = 19 * gst.SECOND
 
1679
        self.track_object3.duration = 23 * gst.SECOND
 
1680
 
 
1681
        context = TrimEndContext(self.timeline, self.track_object1, self.other)
 
1682
        context.editTo(gst.SECOND * 10, 0)
 
1683
        context.finish()
 
1684
 
 
1685
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1686
        self.failUnlessEqual(self.track_object1.in_point, 3 * gst.SECOND)
 
1687
        self.failUnlessEqual(self.track_object1.duration, 9 * gst.SECOND)
 
1688
        self.failUnlessEqual(self.track_object2.start, 16 * gst.SECOND)
 
1689
        self.failUnlessEqual(self.track_object2.in_point, 10 * gst.SECOND)
 
1690
        self.failUnlessEqual(self.track_object2.duration, 16 * gst.SECOND)
 
1691
        self.failUnlessEqual(self.track_object3.start, 32 * gst.SECOND)
 
1692
        self.failUnlessEqual(self.track_object3.in_point, 19 * gst.SECOND)
 
1693
        self.failUnlessEqual(self.track_object3.duration, 23 * gst.SECOND)
 
1694
 
 
1695
    def testTrimEndContextMargins(self):
 
1696
        self.track_object1.start = 1 * gst.SECOND
 
1697
        self.track_object1.in_point = 2 * gst.SECOND
 
1698
        self.track_object1.duration = 10 * gst.SECOND
 
1699
        self.track_object2.start = 12 * gst.SECOND
 
1700
        self.track_object2.in_point = 3 * gst.SECOND
 
1701
        self.track_object2.duration = 10 * gst.SECOND
 
1702
 
 
1703
        context = TrimEndContext(self.timeline, self.track_object1, self.other)
 
1704
        context.editTo(gst.SECOND * 13, 0)
 
1705
        context.finish()
 
1706
 
 
1707
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1708
        self.failUnlessEqual(self.track_object1.in_point, 2 * gst.SECOND)
 
1709
        self.failUnlessEqual(self.track_object1.duration, 11 * gst.SECOND)
 
1710
        self.failUnlessEqual(self.track_object2.start, 12 * gst.SECOND)
 
1711
        self.failUnlessEqual(self.track_object2.in_point, 3 * gst.SECOND)
 
1712
        self.failUnlessEqual(self.track_object2.duration, 10 * gst.SECOND)
 
1713
 
 
1714
    def testTrimEndContextMarginsDifferentTracks(self):
 
1715
        # start
 
1716
        # track1:  [t1][t2 ]
 
1717
        # track2:             [t3 ]
 
1718
        self.track_object1.start = 1 * gst.SECOND
 
1719
        self.track_object1.duration = 10 * gst.SECOND
 
1720
        self.track_object1.priority = 1
 
1721
        self.track_object2.start = 10 * gst.SECOND
 
1722
        self.track_object2.duration = 10 * gst.SECOND
 
1723
        self.track_object2.timeline_object.factory.duration = 30 * gst.SECOND
 
1724
        self.track_object2.priority = 1
 
1725
        self.track_object3.start = 25 * gst.SECOND
 
1726
        self.track_object3.duration = 10 * gst.SECOND
 
1727
        self.track_object3.priority = 1
 
1728
 
 
1729
        # extend to
 
1730
        # track1:  [t1][t2    ]
 
1731
        # track2:           [t3 ]
 
1732
        context = TrimEndContext(self.timeline, self.track_object2, set([]))
 
1733
        context.editTo(gst.SECOND * 30, 0)
 
1734
        context.finish()
 
1735
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1736
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1737
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1738
        self.failUnlessEqual(self.track_object2.duration, 20 * gst.SECOND)
 
1739
        self.failUnlessEqual(self.track_object3.start, 25 * gst.SECOND)
 
1740
        self.failUnlessEqual(self.track_object3.duration, 10 * gst.SECOND)
 
1741
 
 
1742
    def testTrimStartRipple(self):
 
1743
        # [t2]  [t3]  [t1]
 
1744
 
 
1745
        self.track_object2.start = 1 * gst.SECOND
 
1746
        self.track_object2.duration = 4 * gst.SECOND
 
1747
 
 
1748
        self.track_object3.start = 10 * gst.SECOND
 
1749
        self.track_object3.duration = 5 * gst.SECOND
 
1750
 
 
1751
        self.track_object1.start = 15 * gst.SECOND
 
1752
        self.track_object1.duration = 10 * gst.SECOND
 
1753
        self.track_object1.trimStart(20 * gst.SECOND)
 
1754
        # set maximum duration on focus
 
1755
        self.track_object1.factory.duration = 10 * gst.SECOND
 
1756
 
 
1757
        self.failUnlessEqual(self.track_object1.start, 20 * gst.SECOND)
 
1758
        self.failUnlessEqual(self.track_object1.in_point, 5 * gst.SECOND)
 
1759
        self.failUnlessEqual(self.track_object1.duration, 5 * gst.SECOND)
 
1760
 
 
1761
        # test basic trim
 
1762
 
 
1763
        context = TrimStartContext(self.timeline, self.track_object1, self.other)
 
1764
        context.editTo(gst.SECOND * 15, 0)
 
1765
 
 
1766
        self.failUnlessEqual(self.track_object1.start, 15 * gst.SECOND)
 
1767
        self.failUnlessEqual(self.track_object1.in_point, 0 * gst.SECOND)
 
1768
        self.failUnlessEqual(self.track_object2.start, 1 * gst.SECOND)
 
1769
        self.failUnlessEqual(self.track_object2.in_point, 0 * gst.SECOND)
 
1770
        self.failUnlessEqual(self.track_object3.start, 10 * gst.SECOND)
 
1771
        self.failUnlessEqual(self.track_object3.in_point, 0 * gst.SECOND)
 
1772
 
 
1773
        # switch to ripple mode
 
1774
 
 
1775
        context.setMode(context.RIPPLE)
 
1776
 
 
1777
        self.failUnlessEqual(self.track_object1.start, 15 * gst.SECOND)
 
1778
        self.failUnlessEqual(self.track_object1.in_point, 0 * gst.SECOND)
 
1779
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1780
        self.failUnlessEqual(self.track_object2.start, 0 * gst.SECOND)
 
1781
        self.failUnlessEqual(self.track_object2.in_point, 0 * gst.SECOND)
 
1782
        self.failUnlessEqual(self.track_object3.start, 9 * gst.SECOND)
 
1783
        self.failUnlessEqual(self.track_object3.in_point, 0 * gst.SECOND)
 
1784
 
 
1785
        # ripple right
 
1786
 
 
1787
        context.editTo(25 * gst.SECOND, 0)
 
1788
        self.failUnlessEqual(self.track_object1.start, 25 * gst.SECOND)
 
1789
        self.failUnlessEqual(self.track_object1.in_point, 10 * gst.SECOND)
 
1790
        self.failUnlessEqual(self.track_object2.start, 6 * gst.SECOND)
 
1791
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1792
 
 
1793
        # check that ripple is clamped to object duration
 
1794
 
 
1795
        context.editTo(30 * gst.SECOND, 0)
 
1796
        self.failUnlessEqual(self.track_object1.start, 25 * gst.SECOND)
 
1797
        self.failUnlessEqual(self.track_object1.in_point, 10 * gst.SECOND)
 
1798
        self.failUnlessEqual(self.track_object2.start, 6 * gst.SECOND)
 
1799
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1800
 
 
1801
        # test switch back to default
 
1802
 
 
1803
        context.setMode(context.DEFAULT)
 
1804
        self.failUnlessEqual(self.track_object1.start, 25 * gst.SECOND)
 
1805
        self.failUnlessEqual(self.track_object1.in_point, 10 * gst.SECOND)
 
1806
        self.failUnlessEqual(self.track_object2.start, 1 * gst.SECOND)
 
1807
        self.failUnlessEqual(self.track_object3.start, 10 * gst.SECOND)
 
1808
 
 
1809
        # test switch back to ripple
 
1810
 
 
1811
        context.setMode(context.RIPPLE)
 
1812
        self.failUnlessEqual(self.track_object1.start, 25 * gst.SECOND)
 
1813
        self.failUnlessEqual(self.track_object1.in_point, 10 * gst.SECOND)
 
1814
        self.failUnlessEqual(self.track_object2.start, 6 * gst.SECOND)
 
1815
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1816
 
 
1817
        context.finish()
 
1818
 
 
1819
    def testTrimEndContextRipple(self):
 
1820
        # [t1][t2][t3]
 
1821
 
 
1822
        self.track_object1.start = 1 * gst.SECOND
 
1823
        self.track_object1.duration = 4 * gst.SECOND
 
1824
        self.track_object1.factory.duration = 10 * gst.SECOND
 
1825
        self.track_object2.start = 5 * gst.SECOND
 
1826
        self.track_object2.duration = 5 * gst.SECOND
 
1827
        self.track_object3.start = 10 * gst.SECOND
 
1828
        self.track_object3.duration = 5 * gst.SECOND
 
1829
 
 
1830
        # test default trim
 
1831
 
 
1832
        context = TrimEndContext(self.timeline, self.track_object1, self.other)
 
1833
        context.editTo(gst.SECOND * 10, 0)
 
1834
 
 
1835
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1836
        self.failUnlessEqual(self.track_object1.duration, 9 * gst.SECOND)
 
1837
        self.failUnlessEqual(self.track_object2.start, 5 * gst.SECOND)
 
1838
        self.failUnlessEqual(self.track_object2.duration, 5 * gst.SECOND)
 
1839
        self.failUnlessEqual(self.track_object3.start, 10 * gst.SECOND)
 
1840
        self.failUnlessEqual(self.track_object3.duration, 5 * gst.SECOND)
 
1841
 
 
1842
        # switch to ripple mode
 
1843
 
 
1844
        context.setMode(context.RIPPLE)
 
1845
 
 
1846
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1847
        self.failUnlessEqual(self.track_object1.duration, 9 * gst.SECOND)
 
1848
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1849
        self.failUnlessEqual(self.track_object2.duration, 5 * gst.SECOND)
 
1850
        self.failUnlessEqual(self.track_object3.start, 15 * gst.SECOND)
 
1851
        self.failUnlessEqual(self.track_object3.duration, 5 * gst.SECOND)
 
1852
 
 
1853
        context.editTo(gst.SECOND * 10, 0)
 
1854
 
 
1855
        # check that we can't ripple past focal object duration
 
1856
 
 
1857
        context.editTo(gst.SECOND * 15, 0)
 
1858
        self.failUnlessEqual(self.track_object1.duration, 10 * gst.SECOND)
 
1859
        self.failUnlessEqual(self.track_object2.start, 11 * gst.SECOND)
 
1860
        self.failUnlessEqual(self.track_object3.start, 16 * gst.SECOND)
 
1861
 
 
1862
        # check that we can't ripple before initial start of focal object
 
1863
 
 
1864
        context.editTo(0, 0)
 
1865
        self.failUnlessEqual(self.track_object1.duration, 0 * gst.SECOND)
 
1866
        self.failUnlessEqual(self.track_object2.start, 1 * gst.SECOND)
 
1867
        self.failUnlessEqual(self.track_object3.start, 6 * gst.SECOND)
 
1868
 
 
1869
        # switch back to default mode
 
1870
 
 
1871
        context.setMode(context.DEFAULT)
 
1872
 
 
1873
        self.failUnlessEqual(self.track_object1.start, 1 * gst.SECOND)
 
1874
        self.failUnlessEqual(self.track_object1.duration, 0 * gst.SECOND)
 
1875
        self.failUnlessEqual(self.track_object2.start, 5 * gst.SECOND)
 
1876
        self.failUnlessEqual(self.track_object2.duration, 5 * gst.SECOND)
 
1877
        self.failUnlessEqual(self.track_object3.start, 10 * gst.SECOND)
 
1878
        self.failUnlessEqual(self.track_object3.duration, 5 * gst.SECOND)
 
1879
 
 
1880
        # switch back to ripple mode
 
1881
 
 
1882
        context.setMode(context.RIPPLE)
 
1883
 
 
1884
        self.failUnlessEqual(self.track_object1.duration, 0 * gst.SECOND)
 
1885
        self.failUnlessEqual(self.track_object2.start, 1 * gst.SECOND)
 
1886
        self.failUnlessEqual(self.track_object3.start, 6 * gst.SECOND)
 
1887
 
 
1888
        context.finish()
 
1889
 
 
1890
    def testEmptyOther(self):
 
1891
        context = MoveContext(self.timeline, self.track_object1, set())
 
1892
        context.finish()
 
1893
        context = TrimStartContext(self.timeline, self.track_object1, set())
 
1894
        context.finish()
 
1895
        context = TrimEndContext(self.timeline, self.track_object1, set())
 
1896
        context.finish()
 
1897
 
 
1898
    def testNothingToRipple(self):
 
1899
        self.track_object1.start = 20 * gst.SECOND
 
1900
        self.track_object1.duration = 5 * gst.SECOND
 
1901
        self.track_object2.start = 10 * gst.SECOND
 
1902
        self.track_object2.duration = 1 * gst.SECOND
 
1903
        self.track_object2.priority = 1
 
1904
        self.track_object3.start = 11 * gst.SECOND
 
1905
        self.track_object3.duration = 1 * gst.SECOND
 
1906
        self.track_object3.priority = 1
 
1907
 
 
1908
        context = MoveContext(self.timeline, self.track_object1, set())
 
1909
        context.setMode(context.RIPPLE)
 
1910
        context.editTo(10 * gst.SECOND, 0)
 
1911
 
 
1912
        self.failUnlessEqual(self.track_object1.start, 10 * gst.SECOND)
 
1913
        self.failUnlessEqual(self.track_object2.start, 10 * gst.SECOND)
 
1914
        self.failUnlessEqual(self.track_object3.start, 11 * gst.SECOND)
 
1915
 
 
1916
    def tearDown(self):
 
1917
        del self.timeline_object1
 
1918
        del self.timeline_object2
 
1919
        del self.timeline_object3
 
1920
        del self.track_object1
 
1921
        del self.track_object2
 
1922
        del self.track_object3
 
1923
        del self.track1
 
1924
        del self.track2
 
1925
        del self.source_factory
 
1926
        del self.stream
 
1927
        del self.timeline
 
1928
        del self.other
 
1929
        TestCase.tearDown(self)