edl 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -10
- data/Rakefile +10 -22
- data/edl.gemspec +32 -67
- data/lib/edl.rb +115 -116
- data/lib/edl/cutter.rb +15 -12
- data/lib/edl/event.rb +42 -32
- data/lib/edl/grabber.rb +10 -8
- data/lib/edl/linebreak_magician.rb +3 -1
- data/lib/edl/parser.rb +24 -19
- data/lib/edl/timewarp.rb +10 -9
- data/lib/edl/transition.rb +5 -5
- data/lib/edl/version.rb +5 -0
- metadata +20 -71
- data/test/samples/45S_SAMPLE.EDL +0 -48
- data/test/samples/FCP_REVERSE.EDL +0 -9
- data/test/samples/KEY_TRANSITION.EDL +0 -9
- data/test/samples/PLATES.EDL +0 -1
- data/test/samples/REEL_IS_CLIP.txt +0 -8
- data/test/samples/REVERSE.EDL +0 -3
- data/test/samples/SIMPLE_DISSOLVE.EDL +0 -9
- data/test/samples/SPEEDUP_AND_FADEOUT.EDL +0 -11
- data/test/samples/SPEEDUP_REVERSE_AND_FADEOUT.EDL +0 -11
- data/test/samples/SPLICEME.EDL +0 -5
- data/test/samples/TIMEWARP.EDL +0 -5
- data/test/samples/TIMEWARP_HALF.EDL +0 -5
- data/test/samples/TRAILER_EDL.edl +0 -0
- data/test/samples/edl_mixed_line_endings.edl +0 -12
- data/test/test_edl.rb +0 -721
data/test/samples/45S_SAMPLE.EDL
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
TITLE: EDIT 15 [14-11-08] 45 SEC EDL
|
2
|
-
001 106771 V C 04:00:57:05 04:00:58:10 10:00:00:00 10:00:01:05
|
3
|
-
002 106771 V C 04:03:44:06 04:03:45:08 10:00:01:05 10:00:02:07
|
4
|
-
003 106770 V C 00:06:55:13 00:06:57:01 10:00:02:07 10:00:03:20
|
5
|
-
004 106771 V C 03:16:35:05 03:16:36:05 10:00:03:20 10:00:04:20
|
6
|
-
005 106770 V C 00:13:03:17 00:13:04:20 10:00:04:20 10:00:05:23
|
7
|
-
006 106771 V C 03:11:43:02 03:11:44:04 10:00:05:23 10:00:07:00
|
8
|
-
007 106857 V C 07:18:40:24 07:18:41:17 10:00:07:00 10:00:07:18
|
9
|
-
008 106857 V C 07:22:25:19 07:22:27:02 10:00:07:18 10:00:09:01
|
10
|
-
009 106863 V C 13:12:46:23 13:12:48:11 10:00:09:01 10:00:10:14
|
11
|
-
010 106857 V C 08:00:32:00 08:00:33:10 10:00:10:14 10:00:11:24
|
12
|
-
011 106857 V C 08:05:36:18 08:05:37:19 10:00:11:24 10:00:13:00
|
13
|
-
012 106857 V C 07:04:47:06 07:04:50:13 10:00:13:00 10:00:16:07
|
14
|
-
M2 106857 012.5 07:04:47:06
|
15
|
-
013 106863 V C 10:11:06:07 10:11:08:00 10:00:16:07 10:00:18:00
|
16
|
-
014 106863 V C 10:09:16:21 10:09:18:11 10:00:18:00 10:00:19:15
|
17
|
-
015 106857 V C 07:06:02:17 07:06:04:07 10:00:19:15 10:00:21:05
|
18
|
-
016 106857 V C 09:07:18:07 09:07:20:16 10:00:21:05 10:00:23:14
|
19
|
-
M2 106857 002.5 09:07:18:07
|
20
|
-
017 106863 V C 11:02:46:06 11:02:47:06 10:00:23:14 10:00:24:14
|
21
|
-
018 106863 V C 11:10:17:04 11:10:17:20 10:00:24:14 10:00:25:05
|
22
|
-
019 106863 V C 12:06:09:18 12:06:10:16 10:00:25:05 10:00:26:03
|
23
|
-
020 106863 V C 12:10:49:17 12:10:51:02 10:00:26:03 10:00:27:13
|
24
|
-
021 106815 V C 05:01:22:21 05:01:24:05 10:00:27:13 10:00:28:22
|
25
|
-
022 106815 V C 06:01:35:03 06:01:36:18 10:00:28:22 10:00:30:12
|
26
|
-
023 106815 V C 05:13:38:19 05:13:40:10 10:00:30:12 10:00:32:03
|
27
|
-
M2 106815 -025.0 05:13:38:19
|
28
|
-
024 106857 V C 09:13:03:09 09:13:05:11 10:00:32:03 10:00:34:05
|
29
|
-
M2 106857 -025.0 09:13:03:09
|
30
|
-
025 106857 V C 09:13:01:07 09:13:01:07 10:00:34:05 10:00:34:05
|
31
|
-
025 106771 V D 022 03:11:55:00 03:11:56:17 10:00:34:05 10:00:35:22
|
32
|
-
M2 106857 -025.0 09:13:01:07
|
33
|
-
* BLEND, DISSOLVE
|
34
|
-
026 106771 V C 03:11:56:17 03:11:56:17 10:00:35:22 10:00:35:22
|
35
|
-
026 106771 V D 012 03:06:30:09 03:06:31:19 10:00:35:22 10:00:37:07
|
36
|
-
* BLEND, DISSOLVE
|
37
|
-
027 106863 V C 13:15:29:20 13:15:31:02 10:00:37:07 10:00:38:14
|
38
|
-
028 106771 V C 03:15:40:22 03:15:42:11 10:00:38:14 10:00:40:03
|
39
|
-
029 106863 V C 13:15:51:02 13:15:52:08 10:00:40:03 10:00:41:09
|
40
|
-
030 106863 V C 13:15:52:08 13:15:52:08 10:00:41:09 10:00:41:09
|
41
|
-
030 BL V D 032 00:00:00:00 00:00:01:07 10:00:41:09 10:00:42:16
|
42
|
-
* BLEND, DISSOLVE
|
43
|
-
>>> SOURCE 106770 106770 4919975f.793b8d33
|
44
|
-
>>> SOURCE 106771 106771 4919a179.79630563
|
45
|
-
>>> SOURCE 106815 106815 4919b521.79afcb70
|
46
|
-
>>> SOURCE 106857 106857 4919cbb9.7a080d9d
|
47
|
-
>>> SOURCE 106863 106863 4919e0c3.7a5a3cfc
|
48
|
-
|
@@ -1,9 +0,0 @@
|
|
1
|
-
TITLE: FOR_TEST
|
2
|
-
FCM: DROP FRAME
|
3
|
-
|
4
|
-
002 AX V K B 00:01:06:06 00:01:08:03 01:00:04:10 01:00:06:07
|
5
|
-
002 AX V K 000 00:00:03:08 00:00:03:08 01:00:04:10 01:00:04:10
|
6
|
-
* FROM CLIP NAME: foobarz_0118_023-APPLE PRORES WITH ALPHA.MOV
|
7
|
-
* COMMENT:
|
8
|
-
* KEY CLIP NAME: foobarz_0118_026-APPLE PRORES WITH ALPHA.MOV
|
9
|
-
* CLIP FILTER: COLOR CORRECTOR 3-WAY
|
data/test/samples/PLATES.EDL
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
TITLE: PLATES.
|
@@ -1,8 +0,0 @@
|
|
1
|
-
0001 KASS1 A1234V C 00:00:00:00 00:00:12:24 10:00:00:00 10:00:12:24
|
2
|
-
* REEL RC100009 IS CLIP 28661.mov
|
3
|
-
0002 KASS1 A1234V C 00:00:00:00 00:00:13:03 10:00:12:24 10:00:26:02
|
4
|
-
* REEL RC100003 IS CLIP 28655.mov
|
5
|
-
0003 KASS1 A1234V C 00:00:00:00 00:00:15:06 10:00:26:02 10:00:41:08
|
6
|
-
* REEL RC100005 IS CLIP 28657.mov
|
7
|
-
0004 KASS1 A1234V C 00:00:00:00 00:00:16:06 10:00:41:08 10:00:57:14
|
8
|
-
* REEL RC100010 IS CLIP 28662.mov
|
data/test/samples/REVERSE.EDL
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
TITLE: SPEEDUP_AND_FADEOUT
|
2
|
-
FCM: NON-DROP FRAME
|
3
|
-
|
4
|
-
001 FOO V C 01:00:00:00 01:00:27:14 01:00:00:00 01:00:27:14
|
5
|
-
001 BL V D 025 00:00:00:00 00:00:01:00 01:00:27:14 01:00:28:14
|
6
|
-
* EFFECT NAME: CROSS DISSOLVE
|
7
|
-
* FROM CLIP NAME: BARS_40S.MOV
|
8
|
-
* COMMENT:
|
9
|
-
M2 FOO 035.0 01:00:00:00
|
10
|
-
|
11
|
-
|
@@ -1,11 +0,0 @@
|
|
1
|
-
TITLE: TESTREV
|
2
|
-
FCM: NON-DROP FRAME
|
3
|
-
|
4
|
-
001 FOO V C 01:00:39:23 01:01:07:12 01:00:00:00 01:00:27:14
|
5
|
-
001 BL V D 025 00:00:00:00 00:00:01:00 01:00:27:14 01:00:28:14
|
6
|
-
* EFFECT NAME: CROSS DISSOLVE
|
7
|
-
* FROM CLIP NAME: BARS_40S.MOV
|
8
|
-
* COMMENT:
|
9
|
-
M2 FOO -035.0 01:00:39:23
|
10
|
-
|
11
|
-
|
data/test/samples/SPLICEME.EDL
DELETED
data/test/samples/TIMEWARP.EDL
DELETED
Binary file
|
data/test/test_edl.rb
DELETED
@@ -1,721 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
require "bundler"
|
3
|
-
Bundler.require(:default, :development)
|
4
|
-
require 'flexmock/test_unit'
|
5
|
-
|
6
|
-
|
7
|
-
require File.dirname(__FILE__) + '/../lib/edl'
|
8
|
-
require File.dirname(__FILE__) + '/../lib/edl/cutter'
|
9
|
-
require File.dirname(__FILE__) + '/../lib/edl/grabber'
|
10
|
-
|
11
|
-
TRAILER_EDL = File.dirname(__FILE__) + '/samples/TRAILER_EDL.edl'
|
12
|
-
SIMPLE_DISSOLVE = File.dirname(__FILE__) + '/samples/SIMPLE_DISSOLVE.EDL'
|
13
|
-
SPLICEME = File.dirname(__FILE__) + '/samples/SPLICEME.EDL'
|
14
|
-
SIMPLE_TIMEWARP = File.dirname(__FILE__) + '/samples/TIMEWARP.EDL'
|
15
|
-
SLOMO_TIMEWARP = File.dirname(__FILE__) + '/samples/TIMEWARP_HALF.EDL'
|
16
|
-
FORTY_FIVER = File.dirname(__FILE__) + '/samples/45S_SAMPLE.EDL'
|
17
|
-
AVID_REVERSE = File.dirname(__FILE__) + '/samples/REVERSE.EDL'
|
18
|
-
SPEEDUP_AND_FADEOUT = File.dirname(__FILE__) + '/samples/SPEEDUP_AND_FADEOUT.EDL'
|
19
|
-
SPEEDUP_REVERSE_AND_FADEOUT = File.dirname(__FILE__) + '/samples/SPEEDUP_REVERSE_AND_FADEOUT.EDL'
|
20
|
-
FCP_REVERSE = File.dirname(__FILE__) + '/samples/FCP_REVERSE.EDL'
|
21
|
-
PLATES = File.dirname(__FILE__) + '/samples/PLATES.EDL'
|
22
|
-
KEY = File.dirname(__FILE__) + '/samples/KEY_TRANSITION.EDL'
|
23
|
-
CLIP_NAMES = File.dirname(__FILE__) + '/samples/REEL_IS_CLIP.txt'
|
24
|
-
MIXED_LINEBREAKS = File.dirname(__FILE__) + '/samples/edl_mixed_line_endings.edl'
|
25
|
-
|
26
|
-
class String
|
27
|
-
def tc(fps = Timecode::DEFAULT_FPS)
|
28
|
-
Timecode.parse(self, fps)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class EDLTest < Test::Unit::TestCase
|
33
|
-
|
34
|
-
def assert_zero(v, message = "Should be zero")
|
35
|
-
assert v.zero?, message
|
36
|
-
end
|
37
|
-
|
38
|
-
context "An Event" do
|
39
|
-
should "support hash initialization" do
|
40
|
-
evt = EDL::Event.new(:src_start_tc => "01:00:00:00".tc)
|
41
|
-
assert_equal "01:00:00:00".tc, evt.src_start_tc
|
42
|
-
end
|
43
|
-
|
44
|
-
should "support block initialization" do
|
45
|
-
evt = EDL::Event.new do | e |
|
46
|
-
e.src_start_tc = "01:00:00:04".tc
|
47
|
-
end
|
48
|
-
assert_equal "01:00:00:04".tc, evt.src_start_tc
|
49
|
-
end
|
50
|
-
|
51
|
-
should "respond to ends_with_transition? with false if outgoing_transition_duration is zero" do
|
52
|
-
evt = EDL::Event.new
|
53
|
-
evt.outgoing_transition_duration = 0
|
54
|
-
assert !evt.ends_with_transition?
|
55
|
-
end
|
56
|
-
|
57
|
-
should "respond to ends_with_transition? with true if outgoing_transition_duration set above zero" do
|
58
|
-
evt = EDL::Event.new
|
59
|
-
evt.outgoing_transition_duration = 24
|
60
|
-
assert evt.ends_with_transition?
|
61
|
-
end
|
62
|
-
|
63
|
-
should "respond to has_timewarp? with false if no timewarp assigned" do
|
64
|
-
evt = EDL::Event.new(:timewarp => nil)
|
65
|
-
assert !evt.has_timewarp?
|
66
|
-
end
|
67
|
-
|
68
|
-
should "respond to has_timewarp? with true if a timewarp is assigned" do
|
69
|
-
evt = EDL::Event.new(:timewarp => true)
|
70
|
-
assert evt.has_timewarp?
|
71
|
-
end
|
72
|
-
|
73
|
-
should "report rec_length as a difference of record timecodes" do
|
74
|
-
evt = EDL::Event.new(:rec_start_tc => "1h".tc, :rec_end_tc => "1h 10s 2f".tc )
|
75
|
-
assert_equal "10s 2f".tc.to_i, evt.rec_length
|
76
|
-
end
|
77
|
-
|
78
|
-
should "report rec_length_with_transition as a difference of record timecodes if no transition set" do
|
79
|
-
evt = EDL::Event.new(:rec_start_tc => "1h".tc, :rec_end_tc => "1h 10s 2f".tc, :outgoing_transition_duration => 0)
|
80
|
-
assert_equal "10s 2f".tc.to_i, evt.rec_length_with_transition
|
81
|
-
end
|
82
|
-
|
83
|
-
should "add transition length to rec_length_with_transition if a transition is set" do
|
84
|
-
evt = EDL::Event.new(:rec_start_tc => "1h".tc, :rec_end_tc => "1h 10s 2f".tc, :outgoing_transition_duration => 10)
|
85
|
-
assert_equal "10s 2f".tc.to_i + 10, evt.rec_length_with_transition
|
86
|
-
end
|
87
|
-
|
88
|
-
should "return a default array for comments" do
|
89
|
-
assert_kind_of Enumerable, EDL::Event.new.comments
|
90
|
-
end
|
91
|
-
|
92
|
-
should "respond false to has_transition? if incoming transition is set" do
|
93
|
-
assert !EDL::Event.new(:transition => nil).has_transition?
|
94
|
-
end
|
95
|
-
|
96
|
-
should "respond true to has_transition? if incoming transition is set" do
|
97
|
-
assert EDL::Event.new(:transition => true).has_transition?
|
98
|
-
end
|
99
|
-
|
100
|
-
should "respond true to black? if reel is BL" do
|
101
|
-
assert EDL::Event.new(:reel => "BL").black?
|
102
|
-
assert !EDL::Event.new(:reel => "001").black?
|
103
|
-
end
|
104
|
-
|
105
|
-
should "respond true to generator? if reel is BL or AX" do
|
106
|
-
assert EDL::Event.new(:reel => "BL").generator?
|
107
|
-
assert EDL::Event.new(:reel => "AX").generator?
|
108
|
-
assert !EDL::Event.new(:reel => "001").generator?
|
109
|
-
end
|
110
|
-
|
111
|
-
should "report src_length as rec_length_with_transition" do
|
112
|
-
e = EDL::Event.new(:rec_start_tc => "2h".tc, :rec_end_tc => "2h 2s".tc)
|
113
|
-
assert_equal "2s".tc.to_i, e.src_length
|
114
|
-
end
|
115
|
-
|
116
|
-
should "support line_number" do
|
117
|
-
assert_nil EDL::Event.new.line_number
|
118
|
-
assert_equal 3, EDL::Event.new(:line_number => 3).line_number
|
119
|
-
end
|
120
|
-
|
121
|
-
should "support capture_length as an alias to src_length" do
|
122
|
-
tw = flexmock
|
123
|
-
tw.should_receive(:actual_length_of_source).and_return(:something)
|
124
|
-
e = EDL::Event.new(:timewarp => tw)
|
125
|
-
assert_equal e.capture_length, e.src_length
|
126
|
-
end
|
127
|
-
|
128
|
-
should "delegate src_length to the timewarp if it is there" do
|
129
|
-
tw = flexmock
|
130
|
-
tw.should_receive(:actual_length_of_source).and_return(:something).once
|
131
|
-
e = EDL::Event.new(:timewarp => tw)
|
132
|
-
assert_equal :something, e.src_length
|
133
|
-
end
|
134
|
-
|
135
|
-
should "report reverse? and reversed? based on the timewarp" do
|
136
|
-
e = EDL::Event.new(:timewarp => nil)
|
137
|
-
assert !e.reverse?
|
138
|
-
assert !e.reversed?
|
139
|
-
|
140
|
-
tw = flexmock
|
141
|
-
tw.should_receive(:reverse?).and_return(true)
|
142
|
-
|
143
|
-
e = EDL::Event.new(:timewarp => tw)
|
144
|
-
assert e.reverse?
|
145
|
-
assert e.reversed?
|
146
|
-
end
|
147
|
-
|
148
|
-
should "report speed as 100 percent without a timewarp" do
|
149
|
-
e = EDL::Event.new
|
150
|
-
assert_equal 100.0, e.speed
|
151
|
-
end
|
152
|
-
|
153
|
-
should "consult the timewarp for speed" do
|
154
|
-
tw = flexmock
|
155
|
-
tw.should_receive(:speed).and_return(:something)
|
156
|
-
|
157
|
-
e = EDL::Event.new(:timewarp => tw)
|
158
|
-
assert_equal :something, e.speed
|
159
|
-
end
|
160
|
-
|
161
|
-
should "report false for starts_with_transition? if transision is nil" do
|
162
|
-
assert !EDL::Event.new.starts_with_transition?
|
163
|
-
end
|
164
|
-
|
165
|
-
should "report zero for incoming_transition_duration if transision is nil" do
|
166
|
-
assert_zero EDL::Event.new.incoming_transition_duration
|
167
|
-
end
|
168
|
-
|
169
|
-
should "report true for starts_with_transition? if transision is not nil" do
|
170
|
-
e = EDL::Event.new :transition => true
|
171
|
-
assert e.starts_with_transition?
|
172
|
-
end
|
173
|
-
|
174
|
-
should "consult the transition for incoming_transition_duration if it's present" do
|
175
|
-
tr = flexmock
|
176
|
-
tr.should_receive(:duration).and_return(:something)
|
177
|
-
|
178
|
-
e = EDL::Event.new(:transition => tr)
|
179
|
-
assert_equal :something, e.incoming_transition_duration
|
180
|
-
end
|
181
|
-
|
182
|
-
should "report capture_from_tc as the source start without a timewarp" do
|
183
|
-
e = EDL::Event.new(:src_start_tc => "1h".tc)
|
184
|
-
assert_equal "1h".tc, e.capture_from_tc
|
185
|
-
end
|
186
|
-
|
187
|
-
should "consult the timewarp for capture_from_tc if a timewarp is there" do
|
188
|
-
tw = flexmock
|
189
|
-
tw.should_receive(:source_used_from).and_return(:something)
|
190
|
-
|
191
|
-
e = EDL::Event.new(:timewarp => tw)
|
192
|
-
assert_equal :something, e.capture_from_tc
|
193
|
-
end
|
194
|
-
|
195
|
-
should "report capture_to_tc as record length plus transition when no timewarp present" do
|
196
|
-
e = EDL::Event.new(:src_end_tc => "1h 10s".tc, :outgoing_transition_duration => 2 )
|
197
|
-
assert_equal "1h 10s 2f".tc, e.capture_to_tc
|
198
|
-
end
|
199
|
-
|
200
|
-
should "report capture_to_and_including_tc as record length plus transition when no timewarp present" do
|
201
|
-
e = EDL::Event.new(:src_end_tc => "1h 10s".tc, :outgoing_transition_duration => 2 )
|
202
|
-
assert_equal "1h 10s 1f".tc, e.capture_to_and_including_tc
|
203
|
-
end
|
204
|
-
|
205
|
-
should "consult the timewarp for capture_to_tc if timewarp is present" do
|
206
|
-
tw = flexmock
|
207
|
-
tw.should_receive(:source_used_upto).and_return(:something)
|
208
|
-
|
209
|
-
e = EDL::Event.new(:timewarp => tw)
|
210
|
-
assert_equal :something, e.capture_to_tc
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
context "A Parser" do
|
215
|
-
should "store the passed framerate" do
|
216
|
-
p = EDL::Parser.new(45)
|
217
|
-
assert_equal 45, p.fps
|
218
|
-
end
|
219
|
-
|
220
|
-
should "return matchers tuned with the passed framerate" do
|
221
|
-
p = EDL::Parser.new(30)
|
222
|
-
matchers = p.get_matchers
|
223
|
-
event_matcher = matchers.find{|e| e.is_a?(EDL::EventMatcher) }
|
224
|
-
assert_equal 30, event_matcher.fps
|
225
|
-
end
|
226
|
-
|
227
|
-
should "create a Timecode from stringified elements" do
|
228
|
-
elems = ["08", "04", "24", "24"]
|
229
|
-
assert_nothing_raised do
|
230
|
-
@tc = EDL::Parser.timecode_from_line_elements(elems, 30)
|
231
|
-
end
|
232
|
-
|
233
|
-
assert_kind_of Timecode, @tc
|
234
|
-
assert_equal "08:04:24:24".tc(30), @tc
|
235
|
-
|
236
|
-
assert_zero elems.length
|
237
|
-
end
|
238
|
-
|
239
|
-
should "parse from a String" do
|
240
|
-
p = EDL::Parser.new
|
241
|
-
assert_nothing_raised do
|
242
|
-
@edl = p.parse File.read(SIMPLE_DISSOLVE)
|
243
|
-
end
|
244
|
-
|
245
|
-
assert_kind_of EDL::List, @edl
|
246
|
-
assert_equal 2, @edl.length
|
247
|
-
end
|
248
|
-
|
249
|
-
should "parse from a File/IOish" do
|
250
|
-
p = EDL::Parser.new
|
251
|
-
assert_nothing_raised do
|
252
|
-
@edl = p.parse File.open(SIMPLE_DISSOLVE)
|
253
|
-
end
|
254
|
-
|
255
|
-
assert_kind_of EDL::List, @edl
|
256
|
-
assert_equal 2, @edl.length
|
257
|
-
end
|
258
|
-
|
259
|
-
should "properly parse a dissolve" do
|
260
|
-
# TODO: reformulate
|
261
|
-
p = EDL::Parser.new
|
262
|
-
@edl = p.parse File.open(SIMPLE_DISSOLVE)
|
263
|
-
|
264
|
-
first, second = @edl
|
265
|
-
|
266
|
-
assert_kind_of EDL::Event, first
|
267
|
-
assert_kind_of EDL::Event, second
|
268
|
-
|
269
|
-
assert second.has_transition?
|
270
|
-
assert first.ends_with_transition?
|
271
|
-
assert !second.ends_with_transition?
|
272
|
-
|
273
|
-
no_trans = @edl.without_transitions
|
274
|
-
|
275
|
-
assert_equal 2, no_trans.length
|
276
|
-
target_tc = (Timecode.parse('01:00:00:00') + 43)
|
277
|
-
assert_equal target_tc, no_trans[0].rec_end_tc,
|
278
|
-
"The incoming clip should have been extended by the length of the dissolve"
|
279
|
-
|
280
|
-
target_tc = Timecode.parse('01:00:00:00')
|
281
|
-
assert_equal target_tc, no_trans[1].rec_start_tc
|
282
|
-
"The outgoing clip should have been left in place"
|
283
|
-
end
|
284
|
-
|
285
|
-
should "return a spliced EDL if the sources allow" do
|
286
|
-
@spliced = EDL::Parser.new.parse(File.open(SPLICEME)).spliced
|
287
|
-
|
288
|
-
assert_equal 1, @spliced.length
|
289
|
-
evt = @spliced[0]
|
290
|
-
|
291
|
-
assert_equal '06:42:50:18'.tc, evt.src_start_tc
|
292
|
-
assert_equal '06:42:52:16'.tc, evt.src_end_tc
|
293
|
-
end
|
294
|
-
|
295
|
-
should "not apply any Matchers if a match is found" do
|
296
|
-
p = EDL::Parser.new
|
297
|
-
m1 = flexmock
|
298
|
-
m1.should_receive(:matches?).with("plop").once.and_return(true)
|
299
|
-
m1.should_receive(:apply).once
|
300
|
-
|
301
|
-
flexmock(p).should_receive(:get_matchers).once.and_return([m1, m1])
|
302
|
-
result = p.parse("plop")
|
303
|
-
assert result.empty?
|
304
|
-
end
|
305
|
-
|
306
|
-
should "register line numbers of the detected events" do
|
307
|
-
p = EDL::Parser.new
|
308
|
-
events = p.parse(File.open(SPLICEME))
|
309
|
-
|
310
|
-
assert_equal 4, events[0].line_number
|
311
|
-
assert_equal 5, events[1].line_number
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
context "A TimewarpMatcher" do
|
316
|
-
|
317
|
-
should "not create any extra events when used within a Parser" do
|
318
|
-
@edl = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP))
|
319
|
-
assert_equal 1, @edl.length
|
320
|
-
end
|
321
|
-
|
322
|
-
should "properly describe a speedup" do
|
323
|
-
clip = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP)).pop
|
324
|
-
|
325
|
-
tw = clip.timewarp
|
326
|
-
|
327
|
-
assert_kind_of EDL::Timewarp, tw
|
328
|
-
assert_operator tw.source_used_upto, :>, clip.src_end_tc
|
329
|
-
|
330
|
-
assert_equal clip.src_start_tc, tw.source_used_from
|
331
|
-
assert_equal 124, clip.timewarp.actual_length_of_source
|
332
|
-
assert !tw.reverse?
|
333
|
-
end
|
334
|
-
|
335
|
-
should "properly describe a slomo" do
|
336
|
-
clip = EDL::Parser.new.parse(File.open(SLOMO_TIMEWARP)).pop
|
337
|
-
|
338
|
-
assert_equal 10, clip.rec_length
|
339
|
-
assert_equal 5, clip.src_length
|
340
|
-
|
341
|
-
tw = clip.timewarp
|
342
|
-
|
343
|
-
assert_operator tw.source_used_upto, :<, clip.src_end_tc
|
344
|
-
|
345
|
-
assert_equal "03:03:19:24".tc, tw.source_used_upto
|
346
|
-
|
347
|
-
assert_equal 50, tw.speed_in_percent.to_i
|
348
|
-
assert_equal 5, tw.actual_length_of_source
|
349
|
-
assert !tw.reverse?
|
350
|
-
end
|
351
|
-
|
352
|
-
end
|
353
|
-
|
354
|
-
context "A reverse timewarp EDL coming from Avid" do
|
355
|
-
|
356
|
-
should "be parsed properly" do
|
357
|
-
|
358
|
-
clip = EDL::Parser.new.parse(File.open(AVID_REVERSE)).pop
|
359
|
-
|
360
|
-
assert_equal 52, clip.rec_length
|
361
|
-
|
362
|
-
tw = clip.timewarp
|
363
|
-
|
364
|
-
assert_equal -25, tw.actual_framerate.to_i
|
365
|
-
assert tw.reverse?
|
366
|
-
assert_equal 52, tw.actual_length_of_source
|
367
|
-
|
368
|
-
assert_equal 52, clip.src_length, "The src length should be computed the same as its just a reverse"
|
369
|
-
assert_equal -100.0, clip.timewarp.speed
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
context "EDL with clip reels in comments" do
|
374
|
-
should "parse clip names into the reel field" do
|
375
|
-
clips = EDL::Parser.new.parse(File.open(CLIP_NAMES))
|
376
|
-
# flunk "This still has to be finalized"
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
context "A Final Cut Pro originating reverse" do
|
381
|
-
|
382
|
-
should "be interpreted properly" do
|
383
|
-
e = EDL::Parser.new.parse(File.open(FCP_REVERSE)).pop
|
384
|
-
|
385
|
-
assert_equal 1000, e.rec_length
|
386
|
-
assert_equal 1000, e.src_length
|
387
|
-
|
388
|
-
assert_equal "1h".tc, e.rec_start_tc
|
389
|
-
assert_equal "1h 40s".tc, e.rec_end_tc
|
390
|
-
|
391
|
-
assert e.reverse?
|
392
|
-
assert_not_nil e.timewarp
|
393
|
-
|
394
|
-
tw = e.timewarp
|
395
|
-
|
396
|
-
assert_equal -100, tw.speed
|
397
|
-
assert_equal e.speed, tw.speed
|
398
|
-
|
399
|
-
assert_equal "1h".tc, tw.source_used_from
|
400
|
-
assert_equal "1h 40s".tc, tw.source_used_upto
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
# context "An edit with keyer transition" do
|
405
|
-
# should "parse correctly" do
|
406
|
-
# events = EDL::Parser.new.parse(File.open(KEY))
|
407
|
-
# assert_equal 2, events.length
|
408
|
-
# flunk "Key transition processing is not reliable yet - no reference"
|
409
|
-
# end
|
410
|
-
# end
|
411
|
-
|
412
|
-
context "EventMatcher" do
|
413
|
-
|
414
|
-
EVT_PATTERNS = [
|
415
|
-
'020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17',
|
416
|
-
'021 009 V C 00:39:04:21 00:39:05:09 01:00:26:17 01:00:27:05',
|
417
|
-
'022 008C V C 08:08:01:23 08:08:02:18 01:00:27:05 01:00:28:00',
|
418
|
-
'023 008C V C 08:07:30:02 08:07:30:21 01:00:28:00 01:00:28:19',
|
419
|
-
'024 AX V C 00:00:00:00 00:00:01:00 01:00:28:19 01:00:29:19',
|
420
|
-
'025 BL V C 00:00:00:00 00:00:00:00 01:00:29:19 01:00:29:19',
|
421
|
-
'025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20',
|
422
|
-
'002 REDACTED V C 03:09:00:13 03:09:55:19 01:00:43:12 01:01:38:18',
|
423
|
-
# '0004 KASS1 A1234V C 00:00:00:00 00:00:16:06 10:00:41:08 10:00:57:14'
|
424
|
-
]
|
425
|
-
|
426
|
-
# should 'handle the event with multiple audio tracks' do
|
427
|
-
# m = EDL::EventMatcher.new(25)
|
428
|
-
#
|
429
|
-
# clip = m.apply([],
|
430
|
-
# '0004 KASS1 A1234V C 00:00:00:00 00:00:16:06 10:00:41:08 10:00:57:14'
|
431
|
-
# )
|
432
|
-
# assert_kind_of EDL::Event, clip
|
433
|
-
# assert_equal "A1234", clip.track
|
434
|
-
# end
|
435
|
-
|
436
|
-
should "produce an Event" do
|
437
|
-
m = EDL::EventMatcher.new(25)
|
438
|
-
|
439
|
-
clip = m.apply([],
|
440
|
-
'020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17'
|
441
|
-
)
|
442
|
-
|
443
|
-
assert_kind_of EDL::Event, clip
|
444
|
-
|
445
|
-
assert_equal "020", clip.num
|
446
|
-
assert_equal "008C", clip.reel
|
447
|
-
assert_equal "V", clip.track
|
448
|
-
|
449
|
-
assert_equal '08:04:24:24'.tc, clip.src_start_tc
|
450
|
-
|
451
|
-
assert_equal '08:04:25:19'.tc, clip.src_end_tc
|
452
|
-
assert_equal '01:00:25:22'.tc, clip.rec_start_tc
|
453
|
-
assert_equal '01:00:26:17'.tc, clip.rec_end_tc
|
454
|
-
|
455
|
-
assert_nil clip.transition
|
456
|
-
assert_nil clip.timewarp
|
457
|
-
assert_zero clip.outgoing_transition_duration
|
458
|
-
end
|
459
|
-
|
460
|
-
should "produce an Event with dissolve" do
|
461
|
-
m = EDL::EventMatcher.new(25)
|
462
|
-
|
463
|
-
dissolve = m.apply([],
|
464
|
-
'025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20'
|
465
|
-
)
|
466
|
-
assert_kind_of EDL::Event, dissolve
|
467
|
-
|
468
|
-
assert_equal "025", dissolve.num
|
469
|
-
assert_equal 'GEN', dissolve.reel
|
470
|
-
assert_equal 'V', dissolve.track
|
471
|
-
assert dissolve.has_transition?
|
472
|
-
|
473
|
-
tr = dissolve.transition
|
474
|
-
|
475
|
-
assert_kind_of EDL::Dissolve, tr
|
476
|
-
assert_equal 25, tr.duration
|
477
|
-
end
|
478
|
-
|
479
|
-
should "produce a vanilla Event with proper source length" do
|
480
|
-
# This one has EXACTLY 4 frames of source
|
481
|
-
m = EDL::EventMatcher.new(25)
|
482
|
-
clip = m.apply([], '001 GEN V C 00:01:00:00 00:01:00:04 01:00:00:00 01:00:00:04')
|
483
|
-
assert_kind_of EDL::Event, clip
|
484
|
-
assert_equal 4, clip.src_length
|
485
|
-
end
|
486
|
-
|
487
|
-
should "set flag on the previous event in the stack when a dissolve is encountered" do
|
488
|
-
m = EDL::EventMatcher.new(25)
|
489
|
-
previous_evt = flexmock
|
490
|
-
previous_evt.should_receive(:outgoing_transition_duration=).with(25).once
|
491
|
-
|
492
|
-
m.apply([previous_evt],
|
493
|
-
'025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20'
|
494
|
-
)
|
495
|
-
end
|
496
|
-
|
497
|
-
should "generate a Wipe" do
|
498
|
-
m = EDL::EventMatcher.new(25)
|
499
|
-
wipe = m.apply([],
|
500
|
-
'025 GEN V W001 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20'
|
501
|
-
)
|
502
|
-
|
503
|
-
tr = wipe.transition
|
504
|
-
assert_kind_of EDL::Wipe, tr
|
505
|
-
assert_equal 25, tr.duration
|
506
|
-
assert_equal '001', tr.smpte_wipe_index
|
507
|
-
end
|
508
|
-
|
509
|
-
EVT_PATTERNS.each do | pat |
|
510
|
-
should "match #{pat.inspect}" do
|
511
|
-
assert EDL::EventMatcher.new(25).matches?(pat)
|
512
|
-
end
|
513
|
-
end
|
514
|
-
|
515
|
-
should "pass the framerate that it received upon instantiation to the Timecodes being created" do
|
516
|
-
|
517
|
-
m = EDL::EventMatcher.new(30)
|
518
|
-
clip = m.apply([],
|
519
|
-
'020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17'
|
520
|
-
)
|
521
|
-
assert_equal 30, clip.rec_start_tc.fps
|
522
|
-
assert_equal 30, clip.rec_end_tc.fps
|
523
|
-
assert_equal 30, clip.src_start_tc.fps
|
524
|
-
assert_equal 30, clip.src_end_tc.fps
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
context "CommentMatcher" do
|
529
|
-
should "match a comment" do
|
530
|
-
line = "* COMMENT: PURE BULLSHIT"
|
531
|
-
assert EDL::CommentMatcher.new.matches?(line)
|
532
|
-
end
|
533
|
-
|
534
|
-
should "apply the comment to the last clip on the stack" do
|
535
|
-
line = "* COMMENT: PURE BULLSHIT"
|
536
|
-
|
537
|
-
comments = []
|
538
|
-
mok_evt = flexmock
|
539
|
-
|
540
|
-
2.times { mok_evt.should_receive(:comments).and_return(comments) }
|
541
|
-
2.times { EDL::CommentMatcher.new.apply([mok_evt], line) }
|
542
|
-
|
543
|
-
assert_equal ["* COMMENT: PURE BULLSHIT", "* COMMENT: PURE BULLSHIT"], mok_evt.comments
|
544
|
-
end
|
545
|
-
end
|
546
|
-
|
547
|
-
context "FallbackMatcher" do
|
548
|
-
should "match anything" do
|
549
|
-
line = "SOME"
|
550
|
-
assert EDL::FallbackMatcher.new.matches?(line)
|
551
|
-
|
552
|
-
line = "OR ANOTHER "
|
553
|
-
assert EDL::FallbackMatcher.new.matches?(line)
|
554
|
-
end
|
555
|
-
|
556
|
-
should "not match whitespace" do
|
557
|
-
line = "\s\s\s\r\n\r"
|
558
|
-
assert !EDL::FallbackMatcher.new.matches?(line)
|
559
|
-
end
|
560
|
-
|
561
|
-
should "append the matched content to comments" do
|
562
|
-
e = flexmock
|
563
|
-
cmts = []
|
564
|
-
e.should_receive(:comments).and_return(cmts)
|
565
|
-
|
566
|
-
EDL::FallbackMatcher.new.apply([e], "FOOBAR")
|
567
|
-
assert_equal ["FOOBAR"], cmts
|
568
|
-
|
569
|
-
EDL::FallbackMatcher.new.apply([e], "FINAL CUT PRO REEL: 006-I REPLACED BY: 006I")
|
570
|
-
assert_equal ["FOOBAR", "FINAL CUT PRO REEL: 006-I REPLACED BY: 006I"], cmts
|
571
|
-
end
|
572
|
-
|
573
|
-
should "raise an ApplyError if no clip is on the stack" do
|
574
|
-
assert_raise(EDL::Matcher::ApplyError) do
|
575
|
-
EDL::FallbackMatcher.new.apply([], "FINAL CUT PRO REEL: 006-I REPLACED BY: 006I")
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
end
|
580
|
-
|
581
|
-
context "ClipNameMatcher" do
|
582
|
-
should "match a clip name" do
|
583
|
-
line = "* FROM CLIP NAME: TAPE_6-10.MOV"
|
584
|
-
assert EDL::NameMatcher.new.matches?(line)
|
585
|
-
end
|
586
|
-
|
587
|
-
should "match a clip name without space after star" do
|
588
|
-
line = "*FROM CLIP NAME: TAPE_6-10.MOV"
|
589
|
-
assert EDL::NameMatcher.new.matches?(line)
|
590
|
-
end
|
591
|
-
|
592
|
-
should "not match a simple comment" do
|
593
|
-
line = "* CRAP"
|
594
|
-
assert !EDL::NameMatcher.new.matches?(line)
|
595
|
-
end
|
596
|
-
|
597
|
-
should "apply the name to the last event on the stack" do
|
598
|
-
line = "* FROM CLIP NAME: TAPE_6-10.MOV"
|
599
|
-
|
600
|
-
mok_evt = flexmock
|
601
|
-
comments = []
|
602
|
-
mok_evt.should_receive(:clip_name=).with('TAPE_6-10.MOV').once
|
603
|
-
mok_evt.should_receive(:comments).and_return(comments).once
|
604
|
-
|
605
|
-
EDL::NameMatcher.new.apply([mok_evt], line)
|
606
|
-
assert_equal ["* FROM CLIP NAME: TAPE_6-10.MOV"], comments
|
607
|
-
end
|
608
|
-
|
609
|
-
end
|
610
|
-
|
611
|
-
context "EffectMatcher" do
|
612
|
-
should "not match a simple comment" do
|
613
|
-
line = "* STUFF"
|
614
|
-
assert !EDL::EffectMatcher.new.matches?(line)
|
615
|
-
end
|
616
|
-
|
617
|
-
should "match a dissolve name" do
|
618
|
-
line = "* EFFECT NAME: CROSS DISSOLVE"
|
619
|
-
assert EDL::EffectMatcher.new.matches?(line)
|
620
|
-
end
|
621
|
-
|
622
|
-
should "match a dissolve name without space after the asterisk" do
|
623
|
-
line = "*EFFECT NAME: CROSS DISSOLVE"
|
624
|
-
assert EDL::EffectMatcher.new.matches?(line)
|
625
|
-
end
|
626
|
-
|
627
|
-
should "apply the effect name to the transition of the last event on the stack" do
|
628
|
-
line = "* EFFECT NAME: CROSS DISSOLVE"
|
629
|
-
mok_evt, mok_transition = flexmock, flexmock
|
630
|
-
cmt = []
|
631
|
-
|
632
|
-
mok_evt.should_receive(:transition).once.and_return(mok_transition)
|
633
|
-
mok_evt.should_receive(:comments).once.and_return(cmt)
|
634
|
-
|
635
|
-
mok_transition.should_receive(:effect=).with("CROSS DISSOLVE").once
|
636
|
-
|
637
|
-
EDL::EffectMatcher.new.apply([mok_evt], line)
|
638
|
-
|
639
|
-
assert_equal ["* EFFECT NAME: CROSS DISSOLVE"], cmt
|
640
|
-
end
|
641
|
-
|
642
|
-
end
|
643
|
-
|
644
|
-
context "An EDL with mixed line breaks" do
|
645
|
-
should 'parse without errors' do
|
646
|
-
list = EDL::Parser.new.parse(File.open(MIXED_LINEBREAKS))
|
647
|
-
assert_equal ["* A", "* B", "* C", "* D", "* E", "* F", "* G"], list[0].comments
|
648
|
-
end
|
649
|
-
end
|
650
|
-
|
651
|
-
context "A complex EDL passed via Parser" do
|
652
|
-
should "parse without errors" do
|
653
|
-
assert_nothing_raised { EDL::Parser.new.parse(File.open(FORTY_FIVER)) }
|
654
|
-
end
|
655
|
-
|
656
|
-
should "parse the EDL with \\r line breaks properly" do
|
657
|
-
evts = EDL::Parser.new.parse(File.read(PLATES))
|
658
|
-
assert_equal 3, evts.length
|
659
|
-
end
|
660
|
-
|
661
|
-
# TODO: this does not belong here
|
662
|
-
should "be properly rewritten from zero" do
|
663
|
-
complex = EDL::Parser.new.parse(File.open(FORTY_FIVER))
|
664
|
-
from_zero = complex.from_zero
|
665
|
-
|
666
|
-
assert_equal complex.length, from_zero.length, "Should have the same number of events"
|
667
|
-
|
668
|
-
assert_zero from_zero[0].rec_start_tc
|
669
|
-
assert_equal '00:00:42:16'.tc, from_zero[-1].rec_end_tc
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
|
-
context "A FinalCutPro speedup with fade at the end" do
|
674
|
-
should "be parsed cleanly" do
|
675
|
-
list = EDL::Parser.new.parse(File.open(SPEEDUP_AND_FADEOUT))
|
676
|
-
|
677
|
-
assert_equal 2, list.length
|
678
|
-
|
679
|
-
first_evt = list[0]
|
680
|
-
|
681
|
-
tw = first_evt.timewarp
|
682
|
-
assert_kind_of EDL::Timewarp, tw
|
683
|
-
|
684
|
-
assert_equal 689, first_evt.rec_length
|
685
|
-
assert_equal 714, first_evt.rec_length_with_transition
|
686
|
-
|
687
|
-
assert_equal 1000, tw.actual_length_of_source
|
688
|
-
assert_equal 140, tw.speed
|
689
|
-
|
690
|
-
assert_equal 1000, first_evt.src_length
|
691
|
-
|
692
|
-
assert_equal "01:00:00:00", first_evt.capture_from_tc.to_s
|
693
|
-
assert_equal "01:00:40:00", first_evt.capture_to_tc.to_s
|
694
|
-
end
|
695
|
-
end
|
696
|
-
|
697
|
-
context "In the trailer EDL the event 4" do
|
698
|
-
should "not have too many comments" do
|
699
|
-
evts = EDL::Parser.new.parse(File.open(TRAILER_EDL))
|
700
|
-
evt = evts[6]
|
701
|
-
assert_equal 5, evt.comments.length
|
702
|
-
end
|
703
|
-
end
|
704
|
-
|
705
|
-
context "A FinalCutPro speedup and reverse with fade at the end" do
|
706
|
-
should "parse cleanly" do
|
707
|
-
first_evt = EDL::Parser.new.parse(File.open(SPEEDUP_REVERSE_AND_FADEOUT)).shift
|
708
|
-
|
709
|
-
assert first_evt.reverse?
|
710
|
-
|
711
|
-
assert_equal 689, first_evt.rec_length
|
712
|
-
assert_equal 714, first_evt.rec_length_with_transition
|
713
|
-
|
714
|
-
tw = first_evt.timewarp
|
715
|
-
|
716
|
-
assert_equal "1h 1f".tc, tw.source_used_from
|
717
|
-
assert_equal "1h 40s".tc, tw.source_used_upto
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
|
-
end
|