edl 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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