edl 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92c9e98e3aae5318b201b581548227410c0add31
4
- data.tar.gz: 775136de2ed133788783aabb995674b68bf610bf
3
+ metadata.gz: aa1756eb9a1a1e9d9c8703e5033741622df904c9
4
+ data.tar.gz: 513d2a6560317fa3fb5988d202219543bf8e0ebe
5
5
  SHA512:
6
- metadata.gz: 64487e6d8b2558e74ae04781a347c2ed91d1c5ad362b764b0af479628077fd70ea831e1df7d1403afabcf794aa10deb1087fa484d7e46f23e70e555b07802ba7
7
- data.tar.gz: 6eb2449c27c2188dcfe11df99b4a987d78436f938fdf7795bc996e7c22dc1d7c3f6b9c42a815f07b79238ae626e8e7b9a3d77576b393c8ed17bdc7151b4835c7
6
+ metadata.gz: 85afdd18d25b711ab61971ac813a79c202a6aa84363fdc47c50de4ca8525e322ca675a22e0002004482420075626ee8ea6dda7088c2d49070687bc6f8efc64d9
7
+ data.tar.gz: e6f3893517e8fc68311816f3b40119ab10d347662f6bb4f6708f78f353a94c74f6b79ffb8683d20b78e671ec11f1dda93a96ae5ecb942ac3532d0ff0bb429fde
@@ -1,44 +1,3 @@
1
- Work with EDL files from Ruby
2
- http://en.wikipedia.org/wiki/Edit_decision_list
3
-
4
- The library assists in parsing [EDL files](http://en.wikipedia.org/wiki/Edit_decision_list) in CMX 3600 format.
5
- You can use it to generate capture lists, inspect needed video segments for the assembled program
6
- and display edit timelines. Together with the depix you could write your own "blind"
7
- conform utility in about 10 minutes, no joke.
8
-
9
- == SYNOPSIS:
10
-
11
- require 'rubygems'
12
- require 'edl'
13
-
14
- list = EDL::Parser.new(fps=25).parse(File.open('OFFLINE.EDL'))
15
- list.events.each do | evt |
16
- evt.clip_name #=> Boat_Trip_Take1
17
- evt.capture_from_tc #=> 01:20:22:10
18
- evt.capture_to_tc #=> 01:20:26:15, accounts for outgoing transition AND M2 timewarps
19
- end
20
-
21
- == REQUIREMENTS:
22
-
23
- * Timecode gem (sudo gem install timecode)
24
-
25
- == PROBLEMS:
26
-
27
- There is currently no support for:
28
-
29
- * drop-frame TC
30
- * audio
31
- * split edits
32
- * key effects
33
-
34
- Some reverse/timewarp combinations can produce source dificiencies of 1 frame
35
-
36
- == INSTALL:
37
-
38
- * sudo gem install edl
39
-
40
- == LICENSE:
41
-
42
1
  (The MIT License)
43
2
 
44
3
  Copyright (c) 2008 Julik Tarkhanov <me@julik.nl>
@@ -0,0 +1,48 @@
1
+ Work with EDL files from Ruby
2
+ http://en.wikipedia.org/wiki/Edit_decision_list
3
+
4
+ The library assists in parsing [EDL files](http://en.wikipedia.org/wiki/Edit_decision_list) in CMX 3600 format.
5
+ You can use it to generate capture lists, inspect needed video segments for the assembled program
6
+ and display edit timelines. When used together with [depix](https://github.com/guerilla-di/depix) you could write your own "blind"
7
+ conform utility in about 10 minutes, no joke.
8
+
9
+ ## Basic usage
10
+
11
+ ```
12
+ require 'rubygems'
13
+ require 'edl'
14
+
15
+ list = EDL::Parser.new(fps=25).parse(File.open('OFFLINE.EDL'))
16
+ list.events.each do | evt |
17
+ evt.clip_name #=> Boat_Trip_Take1
18
+ evt.capture_from_tc #=> 01:20:22:10
19
+ evt.capture_to_tc #=> 01:20:26:15, accounts for outgoing transition AND M2 timewarps
20
+ end
21
+ ```
22
+
23
+ ## Requirements
24
+
25
+ * Timecode gem (sudo gem install timecode)
26
+
27
+ ## Currently unsupportedl EDL features:
28
+
29
+ There is currently no support for:
30
+
31
+ * drop-frame TC
32
+ * audio
33
+ * split edits
34
+ * key effects
35
+
36
+ Some reverse/timewarp combinations can produce source dificiencies of 1 frame
37
+
38
+ ## Installation
39
+
40
+ Add the following to your project `Gemfile`:
41
+
42
+ ```
43
+ gem 'edl'
44
+ ```
45
+
46
+ ## License
47
+
48
+ See LICENSE.txt
data/Rakefile CHANGED
@@ -1,15 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
- require 'bundler/gem_tasks'
4
+ require './lib/edl.rb'
5
5
  require 'rake/testtask'
6
+ require "bundler/gem_tasks"
7
+ require 'rspec/core/rake_task'
6
8
 
7
- begin
8
- require 'rspec/core/rake_task'
9
+ RSpec::Core::RakeTask.new(:spec)
9
10
 
10
- RSpec::Core::RakeTask.new(:spec)
11
-
12
- task default: :spec
13
- rescue LoadError
14
- # no rspec available
15
- end
11
+ task default: :spec
@@ -6,18 +6,26 @@ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
6
6
  require 'edl/version'
7
7
 
8
8
  Gem::Specification.new do |s|
9
+ s.required_rubygems_version = ">= 1.2.0"
10
+
9
11
  s.name = 'edl'
10
12
  s.version = EDL::VERSION
11
-
12
- s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
13
- s.authors = ['Julik Tarkhanov']
13
+ s.authors = ['Julik Tarkhanov', 'Philipp Großelfinger']
14
14
  s.date = '2014-03-24'
15
15
  s.email = 'me@julik.nl'
16
16
  s.extra_rdoc_files = [
17
- 'README.rdoc'
17
+ 'README.md'
18
18
  ]
19
19
 
20
- s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ # Prevent pushing this gem to RubyGemspec.org. To allow pushes either set the 'allowed_push_host'
21
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
22
+ if s.respond_to?(:metadata)
23
+ s.metadata['allowed_push_host'] = "https://rubygems.org"
24
+ else
25
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushespec."
26
+ end
27
+
28
+ s.files = `git ls-files -z`.split("\x0")
21
29
  s.bindir = 'exe'
22
30
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
31
  s.require_paths = ['lib']
@@ -27,19 +35,7 @@ Gem::Specification.new do |s|
27
35
  s.rubygems_version = '2.0.3'
28
36
  s.summary = 'Parser for EDL (Edit Decision List) files'
29
37
 
30
- if s.respond_to? :specification_version
31
- s.specification_version = 4
32
-
33
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0')
34
- s.add_runtime_dependency 'timecode', '>= 0'
35
- s.add_development_dependency 'rake', '>= 0'
36
- s.add_development_dependency 'rspec', '~> 3.5'
37
- else
38
- s.add_dependency 'timecode', '>= 0'
39
- s.add_dependency 'rake', '>= 0'
40
- end
41
- else
42
- s.add_dependency 'timecode', '>= 0'
43
- s.add_dependency 'rake', '>= 0'
44
- end
38
+ s.add_runtime_dependency 'timecode', '>= 0'
39
+ s.add_development_dependency 'rake', '>= 0'
40
+ s.add_development_dependency 'rspec', '~> 3.5'
45
41
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EDL
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.7'
5
5
  end
@@ -0,0 +1,48 @@
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
+ 
@@ -0,0 +1,9 @@
1
+ TITLE: REVSIMPLE
2
+ FCM: NON-DROP FRAME
3
+
4
+ 001 FOO V C 01:00:39:23 01:01:19:23 01:00:00:00 01:00:40:00
5
+ * FROM CLIP NAME: BARS_40S.MOV
6
+ * COMMENT:
7
+ M2 FOO -025.0 01:00:39:23
8
+
9
+ 
@@ -0,0 +1,9 @@
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
@@ -0,0 +1 @@
1
+ TITLE: PLATES.
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,3 @@
1
+ TITLE: REVERSED_EDL
2
+ 001 106857 V C 09:13:03:09 09:13:05:11 10:00:32:03 10:00:34:05
3
+ M2 106857 -025.0 09:13:03:09
@@ -0,0 +1,9 @@
1
+ TITLE: SIMPLE_DISSOLVE
2
+ FCM: NON-DROP FRAME
3
+
4
+ 001 BL V C 00:00:00:00 00:00:00:00 01:00:00:00 01:00:00:00
5
+ 001 006I V D 043 06:42:50:18 06:42:52:13 01:00:00:00 01:00:01:20
6
+ * EFFECT NAME: CROSS DISSOLVE
7
+ * TO CLIP NAME: TAPE_6-10.MOV
8
+ * COMMENT:
9
+
@@ -0,0 +1,11 @@
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
+ 
@@ -0,0 +1,11 @@
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
+ 
@@ -0,0 +1,5 @@
1
+ TITLE: SPLICEME
2
+ FCM: NON-DROP FRAME
3
+
4
+ 001 006I V C 06:42:50:18 06:42:52:13 01:00:00:00 01:00:01:20
5
+ 002 006I V C 06:42:52:14 06:42:52:16 01:00:10:21 01:00:10:23
@@ -0,0 +1,5 @@
1
+ TITLE: TIMEWARP_EDL
2
+ FCM: NON-DROP FRAME
3
+
4
+ 001 003 V C 03:03:19:19 03:03:20:04 01:00:04:03 01:00:04:13
5
+ M2 003 309.6 03:03:19:19
@@ -0,0 +1,5 @@
1
+ TITLE: TIMEWARP_HALF_EDL
2
+ FCM: NON-DROP FRAME
3
+
4
+ 001 003 V C 03:03:19:19 03:03:20:04 01:00:04:03 01:00:04:13
5
+ M2 003 12.5 03:03:19:19
@@ -0,0 +1,12 @@
1
+ TITLE: EDL_TEST
2
+ FCM: NON-DROP FRAME
3
+
4
+ 000001 A001C004_130917 V C 01:23:39:00 01:23:49:01 10:02:51:10 10:03:01:11
5
+ * A
6
+ * B
7
+ * C
8
+ * D
9
+ * E
10
+ * F
11
+ * G
12
+
@@ -0,0 +1,12 @@
1
+ describe EDL::Parser do
2
+ describe '#parse' do
3
+ it 'reports error when frame exceeds fps' do
4
+ Timecode.add_custom_framerate!(12.0)
5
+ parser = EDL::Parser.new(12)
6
+ parser.parse(File.read('spec/fixtures/files/45S_SAMPLE.EDL'))
7
+ expect(parser.errors.first).to match(
8
+ /There can be no more than 12\.0 frames \@12\.0, got 13/
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,739 @@
1
+ # frozen_string_literal: true
2
+
3
+ TRAILER_EDL = 'spec/fixtures/files/TRAILER_EDL.edl'
4
+ SIMPLE_DISSOLVE = 'spec/fixtures/files/SIMPLE_DISSOLVE.EDL'
5
+ SPLICEME = 'spec/fixtures/files/SPLICEME.EDL'
6
+ SIMPLE_TIMEWARP = 'spec/fixtures/files/TIMEWARP.EDL'
7
+ SLOMO_TIMEWARP = 'spec/fixtures/files/TIMEWARP_HALF.EDL'
8
+ FORTY_FIVER = 'spec/fixtures/files/45S_SAMPLE.EDL'
9
+ AVID_REVERSE = 'spec/fixtures/files/REVERSE.EDL'
10
+ SPEEDUP_AND_FADEOUT = 'spec/fixtures/files/SPEEDUP_AND_FADEOUT.EDL'
11
+ SPEEDUP_REVERSE_AND_FADEOUT = 'spec/fixtures/files/SPEEDUP_REVERSE_AND_FADEOUT.EDL'
12
+ FCP_REVERSE = 'spec/fixtures/files/FCP_REVERSE.EDL'
13
+ PLATES = 'spec/fixtures/files/PLATES.EDL'
14
+ KEY = 'spec/fixtures/files/KEY_TRANSITION.EDL'
15
+ CLIP_NAMES = 'spec/fixtures/files/REEL_IS_CLIP.txt'
16
+ MIXED_LINEBREAKS = 'spec/fixtures/files/edl_mixed_line_endings.edl'
17
+
18
+ class String
19
+ def tc(fps = Timecode::DEFAULT_FPS)
20
+ Timecode.parse(self, fps)
21
+ end
22
+ end
23
+
24
+ describe EDL do
25
+ describe 'An Event' do
26
+ it 'support hash initialization' do
27
+ evt = EDL::Event.new(src_start_tc: '01:00:00:00'.tc)
28
+ expect('01:00:00:00'.tc).to eq evt.src_start_tc
29
+ end
30
+
31
+ it 'support block initialization' do
32
+ evt = EDL::Event.new do |e|
33
+ e.src_start_tc = '01:00:00:04'.tc
34
+ end
35
+ expect('01:00:00:04'.tc).to eq evt.src_start_tc
36
+ end
37
+
38
+ it 'respond to ends_with_transition? with false if outgoing_transition_duration is zero' do
39
+ evt = EDL::Event.new
40
+ evt.outgoing_transition_duration = 0
41
+ expect(evt.ends_with_transition?).to be_falsey
42
+ end
43
+
44
+ it 'respond to ends_with_transition? with true if outgoing_transition_duration set above zero' do
45
+ evt = EDL::Event.new
46
+ evt.outgoing_transition_duration = 24
47
+ expect(evt.ends_with_transition?).to be_truthy
48
+ end
49
+
50
+ it 'respond to has_timewarp? with false if no timewarp assigned' do
51
+ evt = EDL::Event.new(timewarp: nil)
52
+ expect(evt.has_timewarp?).to be_falsey
53
+ end
54
+
55
+ it 'respond to has_timewarp? with true if a timewarp is assigned' do
56
+ evt = EDL::Event.new(timewarp: true)
57
+ expect(evt.has_timewarp?).to be_truthy
58
+ end
59
+
60
+ it 'report rec_length as a difference of record timecodes' do
61
+ evt = EDL::Event.new(rec_start_tc: '1h'.tc, rec_end_tc: '1h 10s 2f'.tc)
62
+ expect('10s 2f'.tc.to_i).to eq evt.rec_length
63
+ end
64
+
65
+ it 'report rec_length_with_transition as a difference of record timecodes if no transition set' do
66
+ evt = EDL::Event.new(rec_start_tc: '1h'.tc, rec_end_tc: '1h 10s 2f'.tc, outgoing_transition_duration: 0)
67
+ expect('10s 2f'.tc.to_i).to eq evt.rec_length_with_transition
68
+ end
69
+
70
+ it 'add transition length to rec_length_with_transition if a transition is set' do
71
+ evt = EDL::Event.new(rec_start_tc: '1h'.tc, rec_end_tc: '1h 10s 2f'.tc, outgoing_transition_duration: 10)
72
+ expect('10s 2f'.tc.to_i + 10).to eq evt.rec_length_with_transition
73
+ end
74
+
75
+ it 'return a default array for comments' do
76
+ expect(EDL::Event.new.comments).to be_a(Enumerable)
77
+ end
78
+
79
+ it 'respond false to has_transition? if incoming transition is set' do
80
+ expect(EDL::Event.new(transition: nil).has_transition?).to be_falsey
81
+ end
82
+
83
+ it 'respond true to has_transition? if incoming transition is set' do
84
+ expect(EDL::Event.new(transition: true).has_transition?).to be_truthy
85
+ end
86
+
87
+ it 'respond true to black? if reel is BL' do
88
+ expect(EDL::Event.new(reel: 'BL')).to be_black
89
+ expect(EDL::Event.new(reel: '001')).to_not be_black
90
+ end
91
+
92
+ it 'respond true to generator? if reel is BL or AX' do
93
+ expect(EDL::Event.new(reel: 'BL')).to be_generator
94
+ expect(EDL::Event.new(reel: 'AX')).to be_generator
95
+ expect(EDL::Event.new(reel: '001')).to_not be_generator
96
+ end
97
+
98
+ it 'report src_length as rec_length_with_transition' do
99
+ e = EDL::Event.new(rec_start_tc: '2h'.tc, rec_end_tc: '2h 2s'.tc)
100
+ expect('2s'.tc.to_i).to eq e.src_length
101
+ end
102
+
103
+ it 'support line_number' do
104
+ expect(EDL::Event.new.line_number).to be_nil
105
+ expect(3).to eq EDL::Event.new(line_number: 3).line_number
106
+ end
107
+
108
+ it 'support capture_length as an alias to src_length' do
109
+ tw = double
110
+ expect(tw).to receive(:actual_length_of_source).twice.and_return(:something)
111
+ e = EDL::Event.new(timewarp: tw)
112
+ expect(e.capture_length).to eq e.src_length
113
+ end
114
+
115
+ it 'delegate src_length to the timewarp if it is there' do
116
+ tw = double
117
+ expect(tw).to receive(:actual_length_of_source).and_return(:something)
118
+ e = EDL::Event.new(timewarp: tw)
119
+ expect(:something).to eq e.src_length
120
+ end
121
+
122
+ it 'report reverse? and reversed? based on the timewarp' do
123
+ e = EDL::Event.new(timewarp: nil)
124
+ expect(e).to_not be_reverse
125
+ expect(e).to_not be_reversed
126
+
127
+ tw = double
128
+ expect(tw).to receive(:reverse?).twice.and_return(true)
129
+
130
+ e = EDL::Event.new(timewarp: tw)
131
+ expect(e).to be_reverse
132
+ expect(e).to be_reversed
133
+ end
134
+
135
+ it 'report speed as 100 percent without a timewarp' do
136
+ e = EDL::Event.new
137
+ expect(100.0).to eq e.speed
138
+ end
139
+
140
+ it 'consult the timewarp for speed' do
141
+ tw = double
142
+ expect(tw).to receive(:speed).and_return(:something)
143
+
144
+ e = EDL::Event.new(timewarp: tw)
145
+ expect(:something).to eq e.speed
146
+ end
147
+
148
+ it 'report false for starts_with_transition? if transision is nil' do
149
+ expect(EDL::Event.new.starts_with_transition?).to be_falsey
150
+ end
151
+
152
+ it 'report zero for incoming_transition_duration if transision is nil' do
153
+ expect(EDL::Event.new.incoming_transition_duration).to be_zero
154
+ end
155
+
156
+ it 'report true for starts_with_transition? if transision is not nil' do
157
+ e = EDL::Event.new transition: true
158
+ expect(e.starts_with_transition?).to be_truthy
159
+ end
160
+
161
+ it "consult the transition for incoming_transition_duration if it's present" do
162
+ tr = double
163
+ expect(tr).to receive(:duration).and_return(:something)
164
+
165
+ e = EDL::Event.new(transition: tr)
166
+ expect(:something).to eq e.incoming_transition_duration
167
+ end
168
+
169
+ it 'report capture_from_tc as the source start without a timewarp' do
170
+ e = EDL::Event.new(src_start_tc: '1h'.tc)
171
+ expect('1h'.tc).to eq e.capture_from_tc
172
+ end
173
+
174
+ it 'consult the timewarp for capture_from_tc if a timewarp is there' do
175
+ tw = double
176
+ expect(tw).to receive(:source_used_from).and_return(:something)
177
+
178
+ e = EDL::Event.new(timewarp: tw)
179
+ expect(:something).to eq e.capture_from_tc
180
+ end
181
+
182
+ it 'report capture_to_tc as record length plus transition when no timewarp present' do
183
+ e = EDL::Event.new(src_end_tc: '1h 10s'.tc, outgoing_transition_duration: 2)
184
+ expect('1h 10s 2f'.tc).to eq e.capture_to_tc
185
+ end
186
+
187
+ it 'report capture_to_and_including_tc as record length plus transition when no timewarp present' do
188
+ e = EDL::Event.new(src_end_tc: '1h 10s'.tc, outgoing_transition_duration: 2)
189
+ expect('1h 10s 1f'.tc).to eq e.capture_to_and_including_tc
190
+ end
191
+
192
+ it 'consult the timewarp for capture_to_tc if timewarp is present' do
193
+ tw = double
194
+ expect(tw).to receive(:source_used_upto).and_return(:something)
195
+
196
+ e = EDL::Event.new(timewarp: tw)
197
+ expect(:something).to eq e.capture_to_tc
198
+ end
199
+ end
200
+
201
+ describe 'A Parser' do
202
+ it 'store the passed framerate' do
203
+ p = EDL::Parser.new(45)
204
+ expect(45).to eq p.fps
205
+ end
206
+
207
+ it 'return matchers tuned with the passed framerate' do
208
+ p = EDL::Parser.new(30)
209
+ matchers = p.get_matchers
210
+ event_matcher = matchers.find { |e| e.is_a?(EDL::EventMatcher) }
211
+ expect(30).to eq event_matcher.fps
212
+ end
213
+
214
+ it 'create a Timecode from stringified elements' do
215
+ elems = %w[08 04 24 24]
216
+ expect do
217
+ @tc = EDL::Parser.timecode_from_line_elements(elems, 30)
218
+ end.to_not raise_error
219
+
220
+ expect(@tc).to be_a(Timecode)
221
+ expect('08:04:24:24'.tc(30)).to eq @tc
222
+
223
+ expect(elems).to be_empty
224
+ end
225
+
226
+ it 'parse from a String' do
227
+ p = EDL::Parser.new
228
+ expect do
229
+ @edl = p.parse File.read(SIMPLE_DISSOLVE)
230
+ end.to_not raise_error
231
+
232
+ expect(@edl).to be_a(EDL::List)
233
+ expect(@edl.length).to eq 2
234
+ end
235
+
236
+ it 'parse from a File/IOish' do
237
+ p = EDL::Parser.new
238
+ expect do
239
+ @edl = p.parse File.open(SIMPLE_DISSOLVE)
240
+ end.to_not raise_error
241
+
242
+ expect(@edl).to be_a(EDL::List)
243
+ expect(@edl.length).to eq 2
244
+ end
245
+
246
+ it 'properly parse a dissolve' do
247
+ # TODO: reformulate
248
+ p = EDL::Parser.new
249
+ @edl = p.parse File.open(SIMPLE_DISSOLVE)
250
+
251
+ first, second = @edl
252
+
253
+ expect(first).to be_a(EDL::Event)
254
+ expect(second).to be_a(EDL::Event)
255
+
256
+ expect(second.has_transition?).to be_truthy
257
+ expect(first.ends_with_transition?).to be_truthy
258
+ expect(second.ends_with_transition?).to be_falsey
259
+
260
+ no_trans = @edl.without_transitions
261
+
262
+ expect(2).to eq no_trans.length
263
+ target_tc = (Timecode.parse('01:00:00:00') + 43)
264
+ expect(target_tc).to eq(no_trans[0].rec_end_tc),
265
+ 'The iitshould have been extended by the length of the dissolve'
266
+
267
+ target_tc = Timecode.parse('01:00:00:00')
268
+ expect(target_tc).to eq no_trans[1].rec_start_tc
269
+ 'The oitshould have been left in place'
270
+ end
271
+
272
+ it 'return a spliced EDL if the sources allow' do
273
+ @spliced = EDL::Parser.new.parse(File.open(SPLICEME)).spliced
274
+
275
+ expect(1).to eq @spliced.length
276
+ evt = @spliced[0]
277
+
278
+ expect('06:42:50:18'.tc).to eq evt.src_start_tc
279
+ expect('06:42:52:16'.tc).to eq evt.src_end_tc
280
+ end
281
+
282
+ it 'not apply any Matchers if a match is found' do
283
+ p = EDL::Parser.new
284
+ m1 = double
285
+ expect(m1).to receive(:matches?).with('plop').and_return(true)
286
+ expect(m1).to receive(:apply)
287
+
288
+ expect(p).to receive(:get_matchers).and_return([m1, m1])
289
+ result = p.parse('plop')
290
+ expect(result).to be_empty
291
+ end
292
+
293
+ it 'register line numbers of the detected events' do
294
+ p = EDL::Parser.new
295
+ events = p.parse(File.open(SPLICEME))
296
+
297
+ expect(4).to eq events[0].line_number
298
+ expect(5).to eq events[1].line_number
299
+ end
300
+ end
301
+
302
+ describe 'A TimewarpMatcher' do
303
+ it 'not create any extra events when used within a Parser' do
304
+ @edl = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP))
305
+ expect(1).to eq @edl.length
306
+ end
307
+
308
+ it 'properly describe a speedup' do
309
+ clip = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP)).pop
310
+
311
+ tw = clip.timewarp
312
+
313
+ expect(tw).to be_a(EDL::Timewarp)
314
+ expect(tw.source_used_upto).to be > clip.src_end_tc
315
+
316
+ expect(clip.src_start_tc).to eq tw.source_used_from
317
+ expect(124).to eq clip.timewarp.actual_length_of_source
318
+ expect(tw).to_not be_reverse
319
+ end
320
+
321
+ it 'properly describe a slomo' do
322
+ clip = EDL::Parser.new.parse(File.open(SLOMO_TIMEWARP)).pop
323
+
324
+ expect(10).to eq clip.rec_length
325
+ expect(5).to eq clip.src_length
326
+
327
+ tw = clip.timewarp
328
+
329
+ expect(tw.source_used_upto).to be < clip.src_end_tc
330
+
331
+ expect('03:03:19:24'.tc).to eq tw.source_used_upto
332
+
333
+ expect(50).to eq tw.speed_in_percent.to_i
334
+ expect(5).to eq tw.actual_length_of_source
335
+ expect(tw).to_not be_reverse
336
+ end
337
+ end
338
+
339
+ describe 'A reverse timewarp EDL coming from Avid' do
340
+ it 'be parsed properly' do
341
+ clip = EDL::Parser.new.parse(File.open(AVID_REVERSE)).pop
342
+
343
+ expect(52).to eq clip.rec_length
344
+
345
+ tw = clip.timewarp
346
+
347
+ expect(-25).to eq tw.actual_framerate.to_i
348
+ expect(tw).to be_reverse
349
+ expect(52).to eq tw.actual_length_of_source
350
+
351
+ expect(-100.0).to eq(clip.timewarp.speed), 'should be computed the same as its just a reverse'
352
+ end
353
+ end
354
+
355
+ describe 'EDL with clip reels in comments' do
356
+ it 'parse clip names into the reel field' do
357
+ clips = EDL::Parser.new.parse(File.open(CLIP_NAMES))
358
+ # flunk "This still has to be finalized"
359
+ end
360
+ end
361
+
362
+ describe 'A Final Cut Pro originating reverse' do
363
+ it 'be interpreted properly' do
364
+ e = EDL::Parser.new.parse(File.open(FCP_REVERSE)).pop
365
+
366
+ expect(1000).to eq e.rec_length
367
+ expect(1000).to eq e.src_length
368
+
369
+ expect('1h'.tc).to eq e.rec_start_tc
370
+ expect('1h 40s'.tc).to eq e.rec_end_tc
371
+
372
+ expect(e).to be_reverse
373
+ expect(e.timewarp).to_not be_nil
374
+
375
+ tw = e.timewarp
376
+
377
+ expect(-100).to eq tw.speed
378
+ expect(e.speed).to eq tw.speed
379
+
380
+ expect('1h'.tc).to eq tw.source_used_from
381
+ expect('1h 40s'.tc).to eq tw.source_used_upto
382
+ end
383
+ end
384
+
385
+ # describe "An edit with keyer transition" do
386
+ # itould "parse correctly" do
387
+ # events = EDL::Parser.new.parse(File.open(KEY))
388
+ # expect(2).to eq events.length
389
+ # flunk "Key transition processing is not reliable yet - no reference"
390
+ # end
391
+ # end
392
+
393
+ describe 'EventMatcher' do
394
+ EVT_PATTERNS = [
395
+ '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17',
396
+ '021 009 V C 00:39:04:21 00:39:05:09 01:00:26:17 01:00:27:05',
397
+ '022 008C V C 08:08:01:23 08:08:02:18 01:00:27:05 01:00:28:00',
398
+ '023 008C V C 08:07:30:02 08:07:30:21 01:00:28:00 01:00:28:19',
399
+ '024 AX V C 00:00:00:00 00:00:01:00 01:00:28:19 01:00:29:19',
400
+ '025 BL V C 00:00:00:00 00:00:00:00 01:00:29:19 01:00:29:19',
401
+ '025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20',
402
+ '002 REDACTED V C 03:09:00:13 03:09:55:19 01:00:43:12 01:01:38:18',
403
+ # '0004 KASS1 A1234V C 00:00:00:00 00:00:16:06 10:00:41:08 10:00:57:14'
404
+ ].freeze
405
+
406
+ # ituld 'handle the event with multiple audio tracks' do
407
+ # m = EDL::EventMatcher.new(25)
408
+ #
409
+ # clip = m.apply([],
410
+ # '0004 KASS1 A1234V C 00:00:00:00 00:00:16:06 10:00:41:08 10:00:57:14'
411
+ # )
412
+ # expect(clip).to be_a(EDL::Event)
413
+ # expect("A1234").to eq clip.track
414
+ # end
415
+
416
+ it 'produce an Event' do
417
+ m = EDL::EventMatcher.new(25)
418
+
419
+ clip = m.apply([],
420
+ '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17')
421
+
422
+ expect(clip).to be_a(EDL::Event)
423
+
424
+ expect('020').to eq clip.num
425
+ expect('008C').to eq clip.reel
426
+ expect('V').to eq clip.track
427
+
428
+ expect('08:04:24:24'.tc).to eq clip.src_start_tc
429
+
430
+ expect('08:04:25:19'.tc).to eq clip.src_end_tc
431
+ expect('01:00:25:22'.tc).to eq clip.rec_start_tc
432
+ expect('01:00:26:17'.tc).to eq clip.rec_end_tc
433
+
434
+ expect(clip.transition).to be_nil
435
+ expect(clip.timewarp).to be_nil
436
+ expect(clip.outgoing_transition_duration).to be_zero
437
+ end
438
+
439
+ it 'produce an Event when reel has dots and output a warning' do
440
+ m = EDL::EventMatcher.new(25)
441
+
442
+ # flexmock($stderr).should_receive(:puts).with("Reel name \"TIRED_EDITOR.MOV\" contains dots or spaces, beware.")
443
+
444
+ clip = m.apply([],
445
+ '020 TIREDEDITOR.MOV V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17')
446
+
447
+ expect(clip).to be_a(EDL::Event)
448
+
449
+ expect('020').to eq clip.num
450
+ expect('TIREDEDITOR.MOV').to eq clip.reel
451
+ expect('V').to eq clip.track
452
+
453
+ expect('08:04:24:24'.tc).to eq clip.src_start_tc
454
+ end
455
+
456
+ it 'produce an Event when reel has asterisks' do
457
+ m = EDL::EventMatcher.new(25)
458
+
459
+ clip = m.apply([],
460
+ '047 *TIRED*EDITOR* V C 00:00:38:15 00:00:39:08 01:06:37:03 01:06:37:20 ')
461
+
462
+ expect(clip).to be_a(EDL::Event)
463
+
464
+ expect('047').to eq clip.num
465
+ expect('*TIRED*EDITOR*').to eq clip.reel
466
+ expect('V').to eq clip.track
467
+
468
+ expect('00:00:38:15'.tc).to eq clip.src_start_tc
469
+ end
470
+
471
+ it 'produce an Event with dissolve' do
472
+ m = EDL::EventMatcher.new(25)
473
+
474
+ dissolve = m.apply([],
475
+ '025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20')
476
+ expect(dissolve).to be_a(EDL::Event)
477
+
478
+ expect('025').to eq dissolve.num
479
+ expect('GEN').to eq dissolve.reel
480
+ expect('V').to eq dissolve.track
481
+ expect(dissolve.has_transition?).to be_truthy
482
+
483
+ tr = dissolve.transition
484
+
485
+ expect(tr).to be_a(EDL::Dissolve)
486
+ expect(25).to eq tr.duration
487
+ end
488
+
489
+ it 'produce a vanilla Event with proper source length' do
490
+ # This one has EXACTLY 4 frames of source
491
+ m = EDL::EventMatcher.new(25)
492
+ clip = m.apply([], '001 GEN V C 00:01:00:00 00:01:00:04 01:00:00:00 01:00:00:04')
493
+ expect(clip).to be_a(EDL::Event)
494
+ expect(4).to eq clip.src_length
495
+ end
496
+
497
+ it 'set flag on the previous event in the stack when a dissolve is encountered' do
498
+ m = EDL::EventMatcher.new(25)
499
+ previous_evt = double
500
+ expect(previous_evt).to receive(:outgoing_transition_duration=).with(25)
501
+
502
+ m.apply([previous_evt],
503
+ '025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20')
504
+ end
505
+
506
+ it 'generate a Wipe' do
507
+ m = EDL::EventMatcher.new(25)
508
+ wipe = m.apply([],
509
+ '025 GEN V W001 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20')
510
+
511
+ tr = wipe.transition
512
+ expect(tr).to be_a(EDL::Wipe)
513
+ expect(25).to eq tr.duration
514
+ expect('001').to eq tr.smpte_wipe_index
515
+ end
516
+
517
+ EVT_PATTERNS.each do |pat|
518
+ it "match #{pat.inspect}" do
519
+ expect(EDL::EventMatcher.new(25).matches?(pat)).to be_truthy
520
+ end
521
+ end
522
+
523
+ it 'pass the framerate that it received upon instantiation to the Timecodes being created' do
524
+ m = EDL::EventMatcher.new(30)
525
+ clip = m.apply([],
526
+ '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17')
527
+ expect(30).to eq clip.rec_start_tc.fps
528
+ expect(30).to eq clip.rec_end_tc.fps
529
+ expect(30).to eq clip.src_start_tc.fps
530
+ expect(30).to eq clip.src_end_tc.fps
531
+ end
532
+ end
533
+
534
+ describe 'CommentMatcher' do
535
+ it 'match a comment' do
536
+ line = '* COMMENT: PURE GARBAGE'
537
+ expect(EDL::CommentMatcher.new.matches?(line)).to be_truthy
538
+ end
539
+
540
+ it 'match a comment that that contains an asterisk' do
541
+ line = '* COMMENT: PURE *GARBAGE*'
542
+ expect(EDL::CommentMatcher.new.matches?(line)).to be_truthy
543
+ end
544
+
545
+ it 'apply the comment to the last clip on the stack' do
546
+ line = '* COMMENT: PURE GARBAGE'
547
+
548
+ comments = []
549
+ mok_evt = double
550
+
551
+ expect(mok_evt).to receive(:comments).exactly(3).times.and_return(comments)
552
+ 2.times { EDL::CommentMatcher.new.apply([mok_evt], line) }
553
+
554
+ expect(['* COMMENT: PURE GARBAGE', '* COMMENT: PURE GARBAGE']).to eq mok_evt.comments
555
+ end
556
+ end
557
+
558
+ describe 'FallbackMatcher' do
559
+ it 'match anything' do
560
+ line = 'SOME'
561
+ expect(EDL::FallbackMatcher.new.matches?(line)).to be_truthy
562
+
563
+ line = 'OR ANOTHER '
564
+ expect(EDL::FallbackMatcher.new.matches?(line)).to be_truthy
565
+ end
566
+
567
+ it 'not match whitespace' do
568
+ line = "\s\s\s\r\n\r"
569
+ expect(EDL::FallbackMatcher.new.matches?(line)).to be_falsey
570
+ end
571
+
572
+ it 'append the matched content to comments' do
573
+ e = double
574
+ cmts = []
575
+ expect(e).to receive(:comments).twice.and_return(cmts)
576
+
577
+ EDL::FallbackMatcher.new.apply([e], 'FOOBAR')
578
+ expect(['FOOBAR']).to eq cmts
579
+
580
+ EDL::FallbackMatcher.new.apply([e], 'FINAL CUT PRO REEL: 006-I REPLACED BY: 006I')
581
+ expect(['FOOBAR', 'FINAL CUT PRO REEL: 006-I REPLACED BY: 006I']).to eq cmts
582
+ end
583
+
584
+ it 'raise an ApplyError if no clip is on the stack' do
585
+ expect do
586
+ EDL::FallbackMatcher.new.apply([], 'FINAL CUT PRO REEL: 006-I REPLACED BY: 006I')
587
+ end.to raise_error(EDL::Matcher::ApplyError)
588
+ end
589
+ end
590
+
591
+ describe 'ClipNameMatcher' do
592
+ it 'match a clip name' do
593
+ line = '* FROM CLIP NAME: TAPE_6-10.MOV'
594
+ expect(EDL::NameMatcher.new.matches?(line)).to be_truthy
595
+ end
596
+
597
+ it 'match a clip name without space after star' do
598
+ line = '*FROM CLIP NAME: TAPE_6-10.MOV'
599
+ expect(EDL::NameMatcher.new.matches?(line)).to be_truthy
600
+ end
601
+
602
+ it 'match a clip name containing an asterisk' do
603
+ line = '* FROM CLIP NAME: 18B_1*'
604
+ expect(EDL::NameMatcher.new.matches?(line)).to be_truthy
605
+ end
606
+
607
+ it 'not match a simple comment' do
608
+ line = '* JUNK'
609
+ expect(EDL::NameMatcher.new.matches?(line)).to be_falsey
610
+ end
611
+
612
+ it 'apply the name to the last event on the stack' do
613
+ line = '* FROM CLIP NAME: TAPE_6-10.MOV'
614
+
615
+ mok_evt = double
616
+ comments = []
617
+ expect(mok_evt).to receive(:clip_name=).with('TAPE_6-10.MOV')
618
+ expect(mok_evt).to receive(:comments).and_return(comments)
619
+
620
+ EDL::NameMatcher.new.apply([mok_evt], line)
621
+ expect(['* FROM CLIP NAME: TAPE_6-10.MOV']).to eq comments
622
+ end
623
+ end
624
+
625
+ describe 'EffectMatcher' do
626
+ it 'not match a simple comment' do
627
+ line = '* STUFF'
628
+ expect(EDL::EffectMatcher.new.matches?(line)).to be_falsey
629
+ end
630
+
631
+ it 'match a dissolve name' do
632
+ line = '* EFFECT NAME: CROSS DISSOLVE'
633
+ expect(EDL::EffectMatcher.new.matches?(line)).to be_truthy
634
+ end
635
+
636
+ it 'match a dissolve name without space after the asterisk' do
637
+ line = '*EFFECT NAME: CROSS DISSOLVE'
638
+ expect(EDL::EffectMatcher.new.matches?(line)).to be_truthy
639
+ end
640
+
641
+ it 'match a dissolve name containing an asterisk' do
642
+ line = '* EFFECT NAME: *CROSS DISSOLVE'
643
+ expect(EDL::EffectMatcher.new.matches?(line)).to be_truthy
644
+ end
645
+
646
+ it 'apply the effect name to the transition of the last event on the stack' do
647
+ line = '* EFFECT NAME: CROSS DISSOLVE'
648
+ mok_evt = double
649
+ mok_transition = double
650
+ cmt = []
651
+
652
+ expect(mok_evt).to receive(:transition).and_return(mok_transition)
653
+ expect(mok_evt).to receive(:comments).and_return(cmt)
654
+
655
+ expect(mok_transition).to receive(:effect=).with('CROSS DISSOLVE')
656
+
657
+ EDL::EffectMatcher.new.apply([mok_evt], line)
658
+
659
+ expect(['* EFFECT NAME: CROSS DISSOLVE']).to eq cmt
660
+ end
661
+ end
662
+
663
+ describe 'An EDL with mixed line breaks' do
664
+ it 'parse without errors' do
665
+ list = EDL::Parser.new.parse(File.open(MIXED_LINEBREAKS))
666
+ expect(['* A', '* B', '* C', '* D', '* E', '* F', '* G']).to eq list[0].comments
667
+ end
668
+ end
669
+
670
+ describe 'A complex EDL passed via Parser' do
671
+ it 'parse without errors' do
672
+ expect { EDL::Parser.new.parse(File.open(FORTY_FIVER)) }.to_not raise_error
673
+ end
674
+
675
+ it 'parse the EDL with \\r line breaks properly' do
676
+ evts = EDL::Parser.new.parse(File.read(PLATES))
677
+ expect(3).to eq evts.length
678
+ end
679
+
680
+ # TODO: this does not belong here
681
+ it 'be properly rewritten from zero' do
682
+ complex = EDL::Parser.new.parse(File.open(FORTY_FIVER))
683
+ from_zero = complex.from_zero
684
+
685
+ expect(complex.length).to eq(from_zero.length), 'Should have the same number of events'
686
+
687
+ expect(from_zero[0].rec_start_tc).to be_zero
688
+ expect('00:00:42:16'.tc).to eq from_zero[-1].rec_end_tc
689
+ end
690
+ end
691
+
692
+ describe 'A FinalCutPro speedup with fade at the end' do
693
+ it 'be parsed cleanly' do
694
+ list = EDL::Parser.new.parse(File.open(SPEEDUP_AND_FADEOUT))
695
+
696
+ expect(2).to eq list.length
697
+
698
+ first_evt = list[0]
699
+
700
+ tw = first_evt.timewarp
701
+ expect(tw).to be_a(EDL::Timewarp)
702
+
703
+ expect(689).to eq first_evt.rec_length
704
+ expect(714).to eq first_evt.rec_length_with_transition
705
+
706
+ expect(1000).to eq tw.actual_length_of_source
707
+ expect(140).to eq tw.speed
708
+
709
+ expect(1000).to eq first_evt.src_length
710
+
711
+ expect('01:00:00:00').to eq first_evt.capture_from_tc.to_s
712
+ expect('01:00:40:00').to eq first_evt.capture_to_tc.to_s
713
+ end
714
+ end
715
+
716
+ describe 'In the trailer EDL the event 4' do
717
+ it 'not have too many comments' do
718
+ evts = EDL::Parser.new.parse(File.open(TRAILER_EDL))
719
+ evt = evts[6]
720
+ expect(5).to eq evt.comments.length
721
+ end
722
+ end
723
+
724
+ describe 'A FinalCutPro speedup and reverse with fade at the end' do
725
+ it 'parse cleanly' do
726
+ first_evt = EDL::Parser.new.parse(File.open(SPEEDUP_REVERSE_AND_FADEOUT)).shift
727
+
728
+ expect(first_evt).to be_reverse
729
+
730
+ expect(689).to eq first_evt.rec_length
731
+ expect(714).to eq first_evt.rec_length_with_transition
732
+
733
+ tw = first_evt.timewarp
734
+
735
+ expect('1h 1f'.tc).to eq tw.source_used_from
736
+ expect('1h 40s'.tc).to eq tw.source_used_upto
737
+ end
738
+ end
739
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'edl'
4
+
5
+ RSpec.configure do |config|
6
+ config.filter_run focus: true
7
+ config.run_all_when_everything_filtered = true
8
+ # rspec-expectations config goes here. You can use an alternate
9
+ # assertion/expectation library such as wrong or the stdlib/minitest
10
+ # assertions if you prefer.
11
+ config.expect_with :rspec do |expectations|
12
+ # This option will default to `true` in RSpec 4. It makes the `description`
13
+ # and `failure_message` of custom matchers include text for helper methods
14
+ # defined using `chain`, e.g.:
15
+ # be_bigger_than(2).and_smaller_than(4).description
16
+ # # => "be bigger than 2 and smaller than 4"
17
+ # ...rather than:
18
+ # # => "be bigger than 2"
19
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
20
+ end
21
+
22
+ # rspec-mocks config goes here. You can use an alternate test double
23
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
24
+ config.mock_with :rspec do |mocks|
25
+ # Prevents you from mocking or stubbing a method that does not exist on
26
+ # a real object. This is generally recommended, and will default to
27
+ # `true` in RSpec 4.
28
+ mocks.verify_partial_doubles = true
29
+ end
30
+ end
metadata CHANGED
@@ -1,10 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
+ - Philipp Großelfinger
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
@@ -57,16 +58,16 @@ email: me@julik.nl
57
58
  executables: []
58
59
  extensions: []
59
60
  extra_rdoc_files:
60
- - README.rdoc
61
+ - README.md
61
62
  files:
62
63
  - ".gitignore"
63
64
  - ".rspec"
64
65
  - ".ruby-gemset"
65
- - ".ruby-version"
66
66
  - ".travis.yml"
67
67
  - Gemfile
68
68
  - History.txt
69
- - README.rdoc
69
+ - LICENSE.txt
70
+ - README.md
70
71
  - Rakefile
71
72
  - edl.gemspec
72
73
  - illustr/edl-explain.ai
@@ -79,9 +80,27 @@ files:
79
80
  - lib/edl/timewarp.rb
80
81
  - lib/edl/transition.rb
81
82
  - lib/edl/version.rb
83
+ - spec/fixtures/files/45S_SAMPLE.EDL
84
+ - spec/fixtures/files/FCP_REVERSE.EDL
85
+ - spec/fixtures/files/KEY_TRANSITION.EDL
86
+ - spec/fixtures/files/PLATES.EDL
87
+ - spec/fixtures/files/REEL_IS_CLIP.txt
88
+ - spec/fixtures/files/REVERSE.EDL
89
+ - spec/fixtures/files/SIMPLE_DISSOLVE.EDL
90
+ - spec/fixtures/files/SPEEDUP_AND_FADEOUT.EDL
91
+ - spec/fixtures/files/SPEEDUP_REVERSE_AND_FADEOUT.EDL
92
+ - spec/fixtures/files/SPLICEME.EDL
93
+ - spec/fixtures/files/TIMEWARP.EDL
94
+ - spec/fixtures/files/TIMEWARP_HALF.EDL
95
+ - spec/fixtures/files/TRAILER_EDL.edl
96
+ - spec/fixtures/files/edl_mixed_line_endings.edl
97
+ - spec/lib/edl/parser_spec.rb
98
+ - spec/lib/edl_spec.rb
99
+ - spec/spec_helper.rb
82
100
  homepage: http://guerilla-di.org/edl
83
101
  licenses: []
84
- metadata: {}
102
+ metadata:
103
+ allowed_push_host: https://rubygems.org
85
104
  post_install_message:
86
105
  rdoc_options: []
87
106
  require_paths:
@@ -95,10 +114,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
114
  requirements:
96
115
  - - ">="
97
116
  - !ruby/object:Gem::Version
98
- version: '0'
117
+ version: 1.2.0
99
118
  requirements: []
100
119
  rubyforge_project:
101
- rubygems_version: 2.6.11
120
+ rubygems_version: 2.4.5.2
102
121
  signing_key:
103
122
  specification_version: 4
104
123
  summary: Parser for EDL (Edit Decision List) files
@@ -1 +0,0 @@
1
- 2.4.1