timecode 2.2.1 → 2.2.3
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 +5 -5
- data/.gitignore +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +1 -13
- data/History.txt +12 -0
- data/Rakefile +3 -20
- data/lib/timecode/version.rb +3 -0
- data/lib/timecode.rb +3 -6
- data/timecode.gemspec +28 -51
- metadata +29 -41
- data/test/test_timecode.rb +0 -662
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4b088cb1d23478711cf52e4162b3d0d5f491eb860f5766e974ab25213d13df84
|
4
|
+
data.tar.gz: 4282bda2694e2ef66121c9bf16dd0bd99725dab8164c56b83c783dad1ab547c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb70a54acff2a2915e86152537bc72a06f78af47f05103467c9016e98686dab75f9497f9778a400bdd8f7b5f1dc25f03607355bb21f75e0db69845cfe5c0e78d
|
7
|
+
data.tar.gz: b861e1b97cbd0bec353e809913700c476f833e60467cb4b5de4ed8c796de39ba3e41e380ca00cd8c7ffcd30c496d235867bd0ecf4c41072b5da70c80b02513f8
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -1,15 +1,3 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
group :development do
|
6
|
-
if RUBY_VERSION < "1.9"
|
7
|
-
gem "jeweler", '1.8.4' # Last one without the stupid nokogiri dependency
|
8
|
-
else
|
9
|
-
gem "jeweler"
|
10
|
-
end
|
11
|
-
|
12
|
-
gem "rake", '~> 10'
|
13
|
-
gem 'git', '1.2.9.1'
|
14
|
-
gem 'minitest'
|
15
|
-
end
|
3
|
+
gemspec
|
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 2.2.3 / 2017-06-04
|
2
|
+
|
3
|
+
* Fix drop-frame timecode handling
|
4
|
+
|
5
|
+
=== 2.2.2 / 2017-06-04
|
6
|
+
|
7
|
+
* Replace jeweler with standard rubygems tasks for rolling releases etc.
|
8
|
+
|
9
|
+
=== 2.2.1 / 2016-06-06
|
10
|
+
|
11
|
+
* Add support for drop-frame timecode with proper calculations (pcipriano)
|
12
|
+
|
1
13
|
=== 2.1.0 / 2015-10-21
|
2
14
|
|
3
15
|
* Allow hour counts larger than 99. Note that when printed using to_s the hours will roll over.
|
data/Rakefile
CHANGED
@@ -1,27 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require 'jeweler'
|
3
|
-
require './lib/timecode'
|
4
|
-
require 'thread'
|
5
|
-
Jeweler::Tasks.new do |gem|
|
6
|
-
gem.version = Timecode::VERSION
|
7
|
-
gem.name = "timecode"
|
8
|
-
gem.summary = "Timecode value class"
|
9
|
-
gem.email = "me@julik.nl"
|
10
|
-
gem.homepage = "http://guerilla-di.org/timecode"
|
11
|
-
gem.authors = ["Julik Tarkhanov"]
|
12
|
-
gem.license = 'MIT'
|
13
|
-
|
14
|
-
# Do not package invisibles
|
15
|
-
gem.files.exclude ".*"
|
16
|
-
end
|
17
|
-
|
1
|
+
require "bundler/gem_tasks"
|
18
2
|
require 'rake/testtask'
|
3
|
+
|
19
4
|
Rake::TestTask.new(:test) do |test|
|
20
5
|
test.libs << 'lib' << 'test'
|
21
6
|
test.pattern = 'test/**/test_*.rb'
|
22
7
|
test.verbose = true
|
23
8
|
end
|
24
9
|
|
25
|
-
|
26
|
-
|
27
|
-
task :default => [ :test ]
|
10
|
+
task :default => :test
|
data/lib/timecode.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Timecode is a convenience object for calculating SMPTE timecode natively.
|
2
2
|
# The promise is that you only have to store two values to know the timecode - the amount
|
3
|
-
# of frames and the framerate.
|
4
|
-
# but we avoid that at this point.
|
3
|
+
# of frames and the framerate.
|
5
4
|
#
|
6
5
|
# You can calculate in timecode objects as well as with conventional integers and floats.
|
7
6
|
# Timecode is immutable and can be used as a value object. Timecode objects are sortable.
|
@@ -12,7 +11,7 @@
|
|
12
11
|
# :mapping => [%w(source_tc_frames total), %w(tape_fps fps)]
|
13
12
|
|
14
13
|
require "approximately"
|
15
|
-
|
14
|
+
require File.dirname(__FILE__) + '/timecode/version'
|
16
15
|
class Timecode
|
17
16
|
|
18
17
|
class ComputationValues
|
@@ -40,8 +39,6 @@ class Timecode
|
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
|
-
VERSION = '2.2.1'
|
44
|
-
|
45
42
|
include Comparable, Approximately
|
46
43
|
|
47
44
|
DEFAULT_FPS = 25.0
|
@@ -212,7 +209,7 @@ class Timecode
|
|
212
209
|
def at(hrs, mins, secs, frames, with_fps = DEFAULT_FPS, drop_frame = false)
|
213
210
|
validate_atoms!(hrs, mins, secs, frames, with_fps)
|
214
211
|
comp = ComputationValues.new(with_fps, drop_frame)
|
215
|
-
if drop_frame && secs == 0 && (mins % 10) && (frames < comp.drop_count)
|
212
|
+
if drop_frame && secs == 0 && (mins % 10 > 0) && (frames < comp.drop_count)
|
216
213
|
frames = comp.drop_count
|
217
214
|
end
|
218
215
|
|
data/timecode.gemspec
CHANGED
@@ -1,57 +1,34 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# stub: timecode 2.2.1 ruby lib
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'timecode/version'
|
6
5
|
|
7
|
-
Gem::Specification.new do |
|
8
|
-
|
9
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "timecode"
|
8
|
+
spec.version = Timecode::VERSION
|
9
|
+
spec.authors = ["Julik Tarkhanov"]
|
10
|
+
spec.email = ["me@julik.nl"]
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
s.date = "2016-06-06"
|
15
|
-
s.email = "me@julik.nl"
|
16
|
-
s.extra_rdoc_files = [
|
17
|
-
"README.rdoc"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
"Gemfile",
|
21
|
-
"History.txt",
|
22
|
-
"README.rdoc",
|
23
|
-
"Rakefile",
|
24
|
-
"lib/timecode.rb",
|
25
|
-
"test/test_timecode.rb",
|
26
|
-
"timecode.gemspec"
|
27
|
-
]
|
28
|
-
s.homepage = "http://guerilla-di.org/timecode"
|
29
|
-
s.licenses = ["MIT"]
|
30
|
-
s.rubygems_version = "2.2.2"
|
31
|
-
s.summary = "Timecode value class"
|
12
|
+
spec.homepage = "http://guerilla-di.org/timecode"
|
13
|
+
spec.summary = "Timecode value class"
|
14
|
+
spec.license = "MIT"
|
32
15
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
s.add_runtime_dependency(%q<approximately>, ["~> 1.1"])
|
38
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
39
|
-
s.add_development_dependency(%q<rake>, ["~> 10"])
|
40
|
-
s.add_development_dependency(%q<git>, ["= 1.2.9.1"])
|
41
|
-
s.add_development_dependency(%q<minitest>, [">= 0"])
|
42
|
-
else
|
43
|
-
s.add_dependency(%q<approximately>, ["~> 1.1"])
|
44
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
45
|
-
s.add_dependency(%q<rake>, ["~> 10"])
|
46
|
-
s.add_dependency(%q<git>, ["= 1.2.9.1"])
|
47
|
-
s.add_dependency(%q<minitest>, [">= 0"])
|
48
|
-
end
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
49
20
|
else
|
50
|
-
|
51
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
52
|
-
s.add_dependency(%q<rake>, ["~> 10"])
|
53
|
-
s.add_dependency(%q<git>, ["= 1.2.9.1"])
|
54
|
-
s.add_dependency(%q<minitest>, [">= 0"])
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
55
22
|
end
|
56
|
-
end
|
57
23
|
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_dependency "approximately", '~> 1.1'
|
30
|
+
|
31
|
+
spec.add_development_dependency "minitest", "~> 1"
|
32
|
+
spec.add_development_dependency "bundler"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timecode
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: approximately
|
@@ -25,80 +25,69 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
28
|
+
name: minitest
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
33
|
+
version: '1'
|
48
34
|
type: :development
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
40
|
+
version: '1'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
42
|
+
name: bundler
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
|
-
- -
|
45
|
+
- - ">="
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
47
|
+
version: '0'
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
|
-
- -
|
52
|
+
- - ">="
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
54
|
+
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: rake
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
|
-
- - "
|
59
|
+
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
61
|
+
version: '10.0'
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
|
-
- - "
|
66
|
+
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
description:
|
84
|
-
email:
|
68
|
+
version: '10.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- me@julik.nl
|
85
72
|
executables: []
|
86
73
|
extensions: []
|
87
|
-
extra_rdoc_files:
|
88
|
-
- README.rdoc
|
74
|
+
extra_rdoc_files: []
|
89
75
|
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
90
78
|
- Gemfile
|
91
79
|
- History.txt
|
92
80
|
- README.rdoc
|
93
81
|
- Rakefile
|
94
82
|
- lib/timecode.rb
|
95
|
-
-
|
83
|
+
- lib/timecode/version.rb
|
96
84
|
- timecode.gemspec
|
97
85
|
homepage: http://guerilla-di.org/timecode
|
98
86
|
licenses:
|
99
87
|
- MIT
|
100
|
-
metadata:
|
101
|
-
|
88
|
+
metadata:
|
89
|
+
allowed_push_host: https://rubygems.org
|
90
|
+
post_install_message:
|
102
91
|
rdoc_options: []
|
103
92
|
require_paths:
|
104
93
|
- lib
|
@@ -113,9 +102,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
102
|
- !ruby/object:Gem::Version
|
114
103
|
version: '0'
|
115
104
|
requirements: []
|
116
|
-
|
117
|
-
|
118
|
-
signing_key:
|
105
|
+
rubygems_version: 3.1.6
|
106
|
+
signing_key:
|
119
107
|
specification_version: 4
|
120
108
|
summary: Timecode value class
|
121
109
|
test_files: []
|
data/test/test_timecode.rb
DELETED
@@ -1,662 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'minitest/spec'
|
3
|
-
require 'minitest/autorun'
|
4
|
-
|
5
|
-
require File.expand_path(File.dirname(__FILE__)) + '/../lib/timecode'
|
6
|
-
|
7
|
-
# Needed for a number of tests from the past
|
8
|
-
Timecode.add_custom_framerate!(10)
|
9
|
-
Timecode.add_custom_framerate!(12.5)
|
10
|
-
Timecode.add_custom_framerate!(57)
|
11
|
-
Timecode.add_custom_framerate!(45)
|
12
|
-
Timecode.add_custom_framerate!(12)
|
13
|
-
|
14
|
-
|
15
|
-
describe "Timecode.new should" do
|
16
|
-
|
17
|
-
it "instantiate from int" do
|
18
|
-
tc = Timecode.new(10)
|
19
|
-
tc.must_be_kind_of Timecode
|
20
|
-
tc.total.must_equal 10
|
21
|
-
end
|
22
|
-
|
23
|
-
it "always coerce FPS to float" do
|
24
|
-
Timecode.new(10, 24).fps.must_be_kind_of(Float)
|
25
|
-
Timecode.new(10, 25.0).fps.must_be_kind_of(Float)
|
26
|
-
Timecode.new(10, 29.97).fps.must_be_kind_of(Float)
|
27
|
-
Timecode.new(10, 59.94).fps.must_be_kind_of(Float)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "create a zero TC with no arguments" do
|
31
|
-
Timecode.new.must_equal Timecode.new(0)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "accept full string SMPTE timecode as well" do
|
35
|
-
Timecode.new("00:25:30:10", 25).must_equal Timecode.parse("00:25:30:10")
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'calculates correctly (spot check with special values)' do
|
39
|
-
lambda{ Timecode.new 496159, 23.976 }.must_be_silent
|
40
|
-
lambda{ Timecode.new 548999, 23.976 }.must_be_silent
|
41
|
-
lambda{ Timecode.new 9662, 29.97 }.must_be_silent
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'calculates seconds correctly for rational fps' do
|
45
|
-
Timecode.new(548999, 23.976).seconds.must_equal 14
|
46
|
-
Timecode.new(9662, 29.97, true).seconds.must_equal 22
|
47
|
-
Timecode.new(1078920, 29.97, true).seconds.must_equal 0
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'calculates timecode correctly for rational fps' do
|
51
|
-
atoms_ok = lambda { |tc, h, m, s, f|
|
52
|
-
tc.hours.must_equal h
|
53
|
-
tc.minutes.must_equal m
|
54
|
-
tc.seconds.must_equal s
|
55
|
-
tc.frames.must_equal f
|
56
|
-
}
|
57
|
-
|
58
|
-
atoms_ok.call(Timecode.new(9662, 29.97, true), 0, 5, 22, 12)
|
59
|
-
atoms_ok.call(Timecode.new(467637, 29.97, true), 4, 20, 3, 15)
|
60
|
-
atoms_ok.call(Timecode.new(1078920, 29.97, true), 10, 0, 0, 0)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe "Timecode.validate_atoms! should" do
|
65
|
-
|
66
|
-
it "disallow more than 999 hrs" do
|
67
|
-
lambda{ Timecode.validate_atoms!(999,0,0,0, 25) }.must_be_silent
|
68
|
-
lambda{ Timecode.validate_atoms!(1000,0,0,0, 25) }.must_raise(Timecode::RangeError)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "disallow more than 59 minutes" do
|
72
|
-
lambda{ Timecode.validate_atoms!(1,60,0,0, 25) }.must_raise(Timecode::RangeError)
|
73
|
-
end
|
74
|
-
|
75
|
-
it "disallow more than 59 seconds" do
|
76
|
-
lambda{ Timecode.validate_atoms!(1,0,60,0, 25) }.must_raise(Timecode::RangeError)
|
77
|
-
end
|
78
|
-
|
79
|
-
it "disallow more frames than what the framerate permits" do
|
80
|
-
lambda{ Timecode.validate_atoms!(1,0,45,25, 25) }.must_raise(Timecode::RangeError)
|
81
|
-
lambda{ Timecode.validate_atoms!(1,0,45,32, 30) }.must_raise(Timecode::RangeError)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "pass validation with usable values" do
|
85
|
-
lambda{ Timecode.validate_atoms!(20, 20, 10, 5, 25)}.must_be_silent
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
describe "Timecode.at should" do
|
90
|
-
|
91
|
-
it "disallow more than 999 hrs" do
|
92
|
-
lambda{ Timecode.at(999,0,0,0) }.must_be_silent
|
93
|
-
lambda{ Timecode.at(1000,0,0,0) }.must_raise(Timecode::RangeError)
|
94
|
-
end
|
95
|
-
|
96
|
-
it "disallow more than 59 minutes" do
|
97
|
-
lambda{ Timecode.at(1,60,0,0) }.must_raise(Timecode::RangeError)
|
98
|
-
end
|
99
|
-
|
100
|
-
it "disallow more than 59 seconds" do
|
101
|
-
lambda{ Timecode.at(1,0,60,0) }.must_raise(Timecode::RangeError)
|
102
|
-
end
|
103
|
-
|
104
|
-
it "disallow more frames than what the framerate permits" do
|
105
|
-
lambda{ Timecode.at(1,0,60,25, 25) }.must_raise(Timecode::RangeError)
|
106
|
-
lambda{ Timecode.at(1,0,60,32, 30) }.must_raise(Timecode::RangeError)
|
107
|
-
end
|
108
|
-
|
109
|
-
it "properly accept usable values" do
|
110
|
-
Timecode.at(20, 20, 10, 5).to_s.must_equal "20:20:10:05"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "A new Timecode object should" do
|
115
|
-
it "be frozen" do
|
116
|
-
# must_be :frozen? is somehow dead too
|
117
|
-
assert Timecode.new(10).frozen?
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe "An existing Timecode should" do
|
122
|
-
|
123
|
-
before do
|
124
|
-
@five_seconds = Timecode.new(5*25, 25)
|
125
|
-
@one_and_a_half_film = (90 * 60) * 24
|
126
|
-
@film_tc = Timecode.new(@one_and_a_half_film, 24)
|
127
|
-
end
|
128
|
-
|
129
|
-
it "report that the framerates are in delta" do
|
130
|
-
tc = Timecode.new(1)
|
131
|
-
tc.framerate_in_delta(25.0000000000000001, 25.0000000000000003).must_equal(true)
|
132
|
-
end
|
133
|
-
|
134
|
-
it "validate equality based on delta" do
|
135
|
-
t1, t2 = Timecode.new(10, 25.0000000000000000000000000001), Timecode.new(10, 25.0000000000000000000000000002)
|
136
|
-
t1.must_equal(t2)
|
137
|
-
end
|
138
|
-
|
139
|
-
it "report total as it's to_i" do
|
140
|
-
Timecode.new(10).to_i.must_equal(10)
|
141
|
-
end
|
142
|
-
|
143
|
-
it "coerce itself to int" do
|
144
|
-
(10 + Timecode.new(2)).must_equal 12
|
145
|
-
end
|
146
|
-
|
147
|
-
it "support hours" do
|
148
|
-
@five_seconds.must_respond_to :hours
|
149
|
-
@five_seconds.hours.must_equal 0
|
150
|
-
@film_tc.hours.must_equal 1
|
151
|
-
end
|
152
|
-
|
153
|
-
it "support minutes" do
|
154
|
-
@five_seconds.must_respond_to :minutes
|
155
|
-
@five_seconds.minutes.must_equal 0
|
156
|
-
@film_tc.minutes.must_equal 30
|
157
|
-
end
|
158
|
-
|
159
|
-
it "support seconds" do
|
160
|
-
@five_seconds.must_respond_to :seconds
|
161
|
-
@five_seconds.seconds.must_equal 5
|
162
|
-
@film_tc.seconds.must_equal 0
|
163
|
-
end
|
164
|
-
|
165
|
-
it "support frames" do
|
166
|
-
@film_tc.frames.must_equal 0
|
167
|
-
end
|
168
|
-
|
169
|
-
it "report frame_interval as a float" do
|
170
|
-
tc = Timecode.new(10)
|
171
|
-
tc.must_respond_to :frame_interval
|
172
|
-
|
173
|
-
tc.frame_interval.must_be_within_delta 0.04, 0.0001
|
174
|
-
tc = Timecode.new(10, 30)
|
175
|
-
tc.frame_interval.must_be_within_delta 0.03333, 0.0001
|
176
|
-
end
|
177
|
-
|
178
|
-
it "be comparable" do
|
179
|
-
(Timecode.new(10) < Timecode.new(9)).must_equal false
|
180
|
-
(Timecode.new(9) < Timecode.new(10)).must_equal true
|
181
|
-
Timecode.new(9).must_equal Timecode.new(9)
|
182
|
-
end
|
183
|
-
|
184
|
-
it "raise on comparison of incompatible timecodes" do
|
185
|
-
lambda { Timecode.new(10, 10) < Timecode.new(10, 20)}.must_raise(Timecode::WrongFramerate)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
#module MiniTest::Assertions
|
190
|
-
# UNDEFINED = MiniTest::Assertions::UNDEFINED
|
191
|
-
# def assert_operator o1, op, o2 = UNDEFINED, msg = nil
|
192
|
-
# puts [o1, op, o2, msg].inspect
|
193
|
-
# return assert_predicate o1, op, msg if UNDEFINED == o2
|
194
|
-
# msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
|
195
|
-
# assert o1.__send__(op, o2), msg
|
196
|
-
# end
|
197
|
-
#end
|
198
|
-
|
199
|
-
describe "A Timecode of zero should" do
|
200
|
-
it "properly respond to zero?" do
|
201
|
-
Timecode.new(0).must_respond_to :zero?
|
202
|
-
# must_be :zero? is somehow broken
|
203
|
-
assert Timecode.new(0).zero?
|
204
|
-
refute Timecode.new(1).zero?
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
describe "Timecode.from_seconds should" do
|
209
|
-
it "properly process this specific case for a float framerate" do
|
210
|
-
float_secs = 89.99165971643036
|
211
|
-
float_fps = 23.9898
|
212
|
-
Timecode.add_custom_framerate!(float_fps)
|
213
|
-
lambda{ Timecode.from_seconds(float_secs, float_fps) }.must_be_silent
|
214
|
-
end
|
215
|
-
|
216
|
-
it "properly process a DF framerate" do
|
217
|
-
Timecode.from_seconds(322.4004, 29.97, true).to_i.must_equal 9662
|
218
|
-
Timecode.from_seconds(600.0, 29.97, true).to_i.must_equal 17982
|
219
|
-
Timecode.from_seconds(15603.5005, 29.97, true).to_i.must_equal 467637
|
220
|
-
Timecode.from_seconds(36000.0, 29.97, true).to_i.must_equal 1078920
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe "Timecode#to_seconds should" do
|
225
|
-
it "return a float" do
|
226
|
-
Timecode.new(0).to_seconds.must_be_kind_of Float
|
227
|
-
end
|
228
|
-
|
229
|
-
it "return the value in seconds" do
|
230
|
-
fps = 24
|
231
|
-
secs = 126.3
|
232
|
-
Timecode.new(fps * secs, fps).to_seconds.must_be_within_delta 126.3, 0.1
|
233
|
-
end
|
234
|
-
|
235
|
-
it "properly roundtrip a value via Timecode.from_seconds" do
|
236
|
-
secs_in = 19.76
|
237
|
-
from_secs = Timecode.from_seconds(secs_in, 25.0)
|
238
|
-
from_secs.total.must_equal 494
|
239
|
-
from_secs.to_seconds.must_be_within_delta secs_in, 0.001
|
240
|
-
|
241
|
-
secs_in = 15603.50
|
242
|
-
from_secs = Timecode.from_seconds(secs_in, 29.97, true)
|
243
|
-
from_secs.total.must_equal 467637
|
244
|
-
from_secs.to_seconds.must_be_within_delta secs_in, 0.005
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
describe "An existing Timecode on inspection should" do
|
249
|
-
it "properly present himself via inspect" do
|
250
|
-
Timecode.new(10, 25).inspect.must_equal "#<Timecode:00:00:00:10 (10F@25.00)>"
|
251
|
-
Timecode.new(10, 12).inspect.must_equal "#<Timecode:00:00:00:10 (10F@12.00)>"
|
252
|
-
end
|
253
|
-
|
254
|
-
it "properly print itself" do
|
255
|
-
Timecode.new(5, 25).to_s.must_equal "00:00:00:05"
|
256
|
-
end
|
257
|
-
|
258
|
-
it "properly print itself with DF" do
|
259
|
-
Timecode.new(9662, 29.97, true).to_s.must_equal "00:05:22;12"
|
260
|
-
Timecode.new(9662, 29.97, false).to_s.must_equal "00:05:22:02"
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
describe "An existing Timecode compared by adjacency" do
|
265
|
-
it "properly detect an adjacent timecode to the left" do
|
266
|
-
Timecode.new(10).must_be :adjacent_to?, Timecode.new(9)
|
267
|
-
Timecode.new(10).wont_be :adjacent_to?, Timecode.new(8)
|
268
|
-
end
|
269
|
-
|
270
|
-
it "properly detect an adjacent DF timecode to the left" do
|
271
|
-
Timecode.new(1800, 29.97, true).must_be :adjacent_to?, Timecode.new(1799, 29.97, true)
|
272
|
-
Timecode.new(1800, 29.97, true).wont_be :adjacent_to?, Timecode.new(1798, 29.97, true)
|
273
|
-
end
|
274
|
-
|
275
|
-
it "properly detect an adjacent timecode to the right" do
|
276
|
-
Timecode.new(10).must_be :adjacent_to?, Timecode.new(11)
|
277
|
-
Timecode.new(10).wont_be :adjacent_to?, Timecode.new(12)
|
278
|
-
end
|
279
|
-
|
280
|
-
it "properly detect an adjacent DF timecode to the right" do
|
281
|
-
Timecode.new(1799, 29.97, true).must_be :adjacent_to?, Timecode.new(1800, 29.97, true)
|
282
|
-
Timecode.new(1799, 29.97, true).wont_be :adjacent_to?, Timecode.new(1801, 29.97, true)
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
describe "A Timecode on conversion should" do
|
287
|
-
it "copy itself with a different framerate" do
|
288
|
-
tc = Timecode.new(1800, 25)
|
289
|
-
at24 = tc.convert(24)
|
290
|
-
at24.total.must_equal 1800
|
291
|
-
at29 = tc.convert(29.97)
|
292
|
-
at29.total.must_equal 1800
|
293
|
-
at29.to_s.must_equal "00:01:00:00"
|
294
|
-
at29DF = tc.convert(29.97, true)
|
295
|
-
at29DF.total.must_equal 1800
|
296
|
-
at29DF.to_s.must_equal "00:01:00;02"
|
297
|
-
|
298
|
-
tc1 = Timecode.new(1800, 23.976, true)
|
299
|
-
at29 = tc1.convert(29.97)
|
300
|
-
at29.total.must_equal 1800
|
301
|
-
at29.to_s.must_equal "00:01:00;02"
|
302
|
-
at29ND = tc1.convert(29.97, false)
|
303
|
-
at29ND.total.must_equal 1800
|
304
|
-
at29ND.to_s.must_equal "00:01:00:00"
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
describe "An existing Timecode used within ranges should" do
|
309
|
-
it "properly provide successive value that is one frame up" do
|
310
|
-
Timecode.new(10).succ.total.must_equal 11
|
311
|
-
Timecode.new(22, 45).succ.must_equal Timecode.new(23, 45)
|
312
|
-
Timecode.new(1799, 29.97, true).succ.must_equal Timecode.new(1800, 29.97, true)
|
313
|
-
end
|
314
|
-
|
315
|
-
it "work as a range member" do
|
316
|
-
r = Timecode.new(10)...Timecode.new(20)
|
317
|
-
r.to_a.length.must_equal 10
|
318
|
-
r.to_a[4].must_equal Timecode.new(14)
|
319
|
-
end
|
320
|
-
|
321
|
-
end
|
322
|
-
|
323
|
-
describe "A Timecode on calculations should" do
|
324
|
-
|
325
|
-
it "support addition" do
|
326
|
-
a, b = Timecode.new(24, 25.000000000000001), Timecode.new(22, 25.000000000000002)
|
327
|
-
(a + b).must_equal Timecode.new(24 + 22, 25.000000000000001)
|
328
|
-
end
|
329
|
-
|
330
|
-
it "should raise on addition if framerates do not match" do
|
331
|
-
lambda{ Timecode.new(10, 25) + Timecode.new(10, 30) }.must_raise(Timecode::WrongFramerate)
|
332
|
-
end
|
333
|
-
|
334
|
-
it "should raise on addition if drop flag mismatches" do
|
335
|
-
lambda{ Timecode.new(10, 29.97, true) + Timecode.new(10, 29.97) }.must_raise(Timecode::WrongDropFlag)
|
336
|
-
end
|
337
|
-
|
338
|
-
it "when added with an integer instead calculate on total" do
|
339
|
-
(Timecode.new(5) + 5).must_equal(Timecode.new(10))
|
340
|
-
end
|
341
|
-
|
342
|
-
it "when adding DF flag is preserved" do
|
343
|
-
a, b = Timecode.new(24, 29.97, true), Timecode.new(22, 29.97, true)
|
344
|
-
c, d = Timecode.new(24, 29.97), Timecode.new(22, 29.97)
|
345
|
-
tcsum = a + b
|
346
|
-
tcsum.must_equal Timecode.new(24 + 22, 29.97, true)
|
347
|
-
tcsum.drop?.must_equal true
|
348
|
-
(c + d).drop?.must_equal false
|
349
|
-
end
|
350
|
-
|
351
|
-
it "support subtraction" do
|
352
|
-
a, b = Timecode.new(10), Timecode.new(4)
|
353
|
-
(a - b).must_equal Timecode.new(6)
|
354
|
-
end
|
355
|
-
|
356
|
-
it "on subtraction of an integer instead calculate on total" do
|
357
|
-
(Timecode.new(15) - 5).must_equal Timecode.new(10)
|
358
|
-
end
|
359
|
-
|
360
|
-
it "raise when subtracting a Timecode with a different framerate" do
|
361
|
-
lambda { Timecode.new(10, 25) - Timecode.new(10, 30) }.must_raise(Timecode::WrongFramerate)
|
362
|
-
end
|
363
|
-
|
364
|
-
it "raise when subtracting a Timecode with a different drop frame flag" do
|
365
|
-
lambda { Timecode.new(10, 29.97, true) - Timecode.new(10, 29.97) }.must_raise(Timecode::WrongDropFlag)
|
366
|
-
end
|
367
|
-
|
368
|
-
it "when subtracting DF flag is preserved" do
|
369
|
-
a, b = Timecode.new(24, 29.97, true), Timecode.new(22, 29.97, true)
|
370
|
-
c, d = Timecode.new(24, 29.97), Timecode.new(22, 29.97)
|
371
|
-
tcsub = a - b
|
372
|
-
tcsub.must_equal Timecode.new(24 - 22, 29.97, true)
|
373
|
-
tcsub.drop?.must_equal true
|
374
|
-
(c - d).drop?.must_equal false
|
375
|
-
end
|
376
|
-
|
377
|
-
it "support multiplication" do
|
378
|
-
(Timecode.new(10) * 10).must_equal(Timecode.new(100))
|
379
|
-
end
|
380
|
-
|
381
|
-
it "raise when the resultig Timecode is negative" do
|
382
|
-
lambda { Timecode.new(10) * -200 }.must_raise(Timecode::RangeError)
|
383
|
-
end
|
384
|
-
|
385
|
-
it "preserves drop frame flag when multiplying" do
|
386
|
-
(Timecode.new(10, 29.97, true) * 10).drop?.must_equal true
|
387
|
-
end
|
388
|
-
|
389
|
-
it "return a Timecode when divided by an Integer" do
|
390
|
-
v = Timecode.new(200) / 20
|
391
|
-
v.must_be_kind_of(Timecode)
|
392
|
-
v.must_equal Timecode.new(10)
|
393
|
-
end
|
394
|
-
|
395
|
-
it "return a number when divided by another Timecode" do
|
396
|
-
v = Timecode.new(200) / Timecode.new(20)
|
397
|
-
v.must_be_kind_of(Numeric)
|
398
|
-
v.must_equal 10
|
399
|
-
end
|
400
|
-
|
401
|
-
it "preserves drop frame flag when dividing" do
|
402
|
-
(Timecode.new(200, 29.97, true) / 20).drop?.must_equal true
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
describe "A Timecode used with fractional number of seconds" do
|
407
|
-
|
408
|
-
it "should properly return fractional seconds" do
|
409
|
-
tc = Timecode.new(100 - 1, fps = 25)
|
410
|
-
tc.frames.must_equal 24
|
411
|
-
|
412
|
-
tc.with_frames_as_fraction.must_equal "00:00:03.96"
|
413
|
-
tc.with_fractional_seconds.must_equal "00:00:03.96"
|
414
|
-
tc.with_srt_fraction.must_equal "00:00:03,96"
|
415
|
-
end
|
416
|
-
|
417
|
-
it "properly translate to frames when instantiated from fractional seconds" do
|
418
|
-
fraction = 7.1
|
419
|
-
tc = Timecode.from_seconds(fraction, 10)
|
420
|
-
tc.to_s.must_equal "00:00:07:01"
|
421
|
-
|
422
|
-
fraction = 7.5
|
423
|
-
tc = Timecode.from_seconds(fraction, 10)
|
424
|
-
tc.to_s.must_equal "00:00:07:05"
|
425
|
-
|
426
|
-
fraction = 7.16
|
427
|
-
tc = Timecode.from_seconds(fraction, 25)
|
428
|
-
tc.to_s.must_equal "00:00:07:04"
|
429
|
-
end
|
430
|
-
|
431
|
-
end
|
432
|
-
|
433
|
-
describe "A custom Timecode descendant should" do
|
434
|
-
class CustomTC < Timecode; end
|
435
|
-
|
436
|
-
it "properly classify on parse" do
|
437
|
-
CustomTC.parse("001").must_be_kind_of CustomTC
|
438
|
-
end
|
439
|
-
|
440
|
-
it "properly classify on at" do
|
441
|
-
CustomTC.at(10,10,10,10).must_be_kind_of CustomTC
|
442
|
-
end
|
443
|
-
|
444
|
-
it "properly classify on calculations" do
|
445
|
-
computed = CustomTC.parse("10h") + Timecode.new(10)
|
446
|
-
computed.must_be_kind_of CustomTC
|
447
|
-
|
448
|
-
computed = CustomTC.parse("10h") - Timecode.new(10)
|
449
|
-
computed.must_be_kind_of CustomTC
|
450
|
-
|
451
|
-
computed = CustomTC.parse("10h") * 5
|
452
|
-
computed.must_be_kind_of CustomTC
|
453
|
-
|
454
|
-
computed = CustomTC.parse("10h") / 5
|
455
|
-
computed.must_be_kind_of CustomTC
|
456
|
-
end
|
457
|
-
|
458
|
-
end
|
459
|
-
|
460
|
-
describe "Timecode.from_filename_in_sequence should" do
|
461
|
-
it "detect the timecode" do
|
462
|
-
tc = Timecode.from_filename_in_sequence("foobar.0000012.jpg", fps = 25)
|
463
|
-
tc.must_equal(Timecode.new(12, 25))
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
describe 'Timecode with hours larger than 99 should' do
|
468
|
-
it 'print itself without rollover' do
|
469
|
-
tc = Timecode.at(129,34,42,5)
|
470
|
-
tc.to_s_without_rollover.must_equal '129:34:42:05'
|
471
|
-
end
|
472
|
-
|
473
|
-
it 'print itself with rollover when using to_smpte' do
|
474
|
-
tc = Timecode.at(129,34,42,5)
|
475
|
-
tc.to_s.must_equal '29:34:42:05'
|
476
|
-
end
|
477
|
-
end
|
478
|
-
|
479
|
-
describe "Timecode.parse should" do
|
480
|
-
|
481
|
-
it "handle complete SMPTE timecode" do
|
482
|
-
simple_tc = "00:10:34:10"
|
483
|
-
Timecode.parse(simple_tc).to_s.must_equal(simple_tc)
|
484
|
-
end
|
485
|
-
|
486
|
-
it "handle complete SMPTE timecode with drop frame flag" do
|
487
|
-
simple_tc = "00:10:34;10"
|
488
|
-
tc = Timecode.parse(simple_tc, 29.97)
|
489
|
-
tc.to_s.must_equal(simple_tc)
|
490
|
-
tc.drop?.must_equal true
|
491
|
-
end
|
492
|
-
|
493
|
-
it "handle complete SMPTE timecode with plus for 24 frames per second" do
|
494
|
-
simple_tc = "00:10:34+10"
|
495
|
-
p = Timecode.parse(simple_tc)
|
496
|
-
p.to_s.must_equal("00:10:34:10")
|
497
|
-
p.fps.must_equal 24
|
498
|
-
end
|
499
|
-
|
500
|
-
it "handle timecode with fractional seconds" do
|
501
|
-
tc = Timecode.parse("10:10:10.2", 25)
|
502
|
-
tc.to_s.must_equal "10:10:10:05"
|
503
|
-
|
504
|
-
tc = Timecode.parse("10:10:10,200", 25)
|
505
|
-
tc.to_s.must_equal "10:10:10:05"
|
506
|
-
end
|
507
|
-
|
508
|
-
it "handle timecode with fractional seconds (euro style, SRT)" do
|
509
|
-
tc = Timecode.parse("10:10:10,200", 25)
|
510
|
-
tc.to_s.must_equal "10:10:10:05"
|
511
|
-
end
|
512
|
-
|
513
|
-
it "handle timecode with ticks" do
|
514
|
-
tc = Timecode.parse("10:10:10:103", 25)
|
515
|
-
tc.to_s.must_equal "10:10:10:10"
|
516
|
-
|
517
|
-
tc = Timecode.parse("10:10:10:249", 25)
|
518
|
-
tc.to_s.must_equal "10:10:10:24"
|
519
|
-
end
|
520
|
-
|
521
|
-
it "raise when there are more than 249 ticks" do
|
522
|
-
lambda {
|
523
|
-
tc = Timecode.parse("10:10:10:250", 25)
|
524
|
-
}.must_raise(Timecode::RangeError)
|
525
|
-
end
|
526
|
-
|
527
|
-
it "handle timecode with fractional seconds with spaces at start and end" do
|
528
|
-
tc = Timecode.parse(" 00:00:01.040 ")
|
529
|
-
tc.to_s.must_equal "00:00:01:01"
|
530
|
-
end
|
531
|
-
|
532
|
-
# I am commenting this one out for now, these were present in some odd subtitle file.
|
533
|
-
# What we probably need is a way for Timecode to "extract" timecodes from a chunk of text.
|
534
|
-
# it "handle timecode with fractional seconds with weirdo UTF spaces at start and end" do
|
535
|
-
# tc = Timecode.parse("00:00:01.040")
|
536
|
-
# tc.to_s.must_equal "00:00:01:01"
|
537
|
-
# end
|
538
|
-
|
539
|
-
it "parse a row of numbers as parts of a timecode starting from the right" do
|
540
|
-
Timecode.parse("10").must_equal Timecode.new(10)
|
541
|
-
Timecode.parse("210").must_equal Timecode.new(60)
|
542
|
-
Timecode.parse("10101010").to_s.must_equal "10:10:10:10"
|
543
|
-
end
|
544
|
-
|
545
|
-
it "parse a number with f suffix as frames" do
|
546
|
-
Timecode.parse("60f").must_equal Timecode.new(60)
|
547
|
-
end
|
548
|
-
|
549
|
-
it "parse a number with s suffix as seconds" do
|
550
|
-
Timecode.parse("2s", 25).must_equal Timecode.new(50, 25)
|
551
|
-
Timecode.parse("2s", 30).must_equal Timecode.new(60, 30)
|
552
|
-
end
|
553
|
-
|
554
|
-
it "parse a number with m suffix as minutes" do
|
555
|
-
Timecode.parse("3m").must_equal Timecode.new(25 * 60 * 3)
|
556
|
-
end
|
557
|
-
|
558
|
-
it "parse a number with h suffix as hours" do
|
559
|
-
Timecode.parse("3h").must_equal Timecode.new(25 * 60 * 60 * 3)
|
560
|
-
end
|
561
|
-
|
562
|
-
it "parse different suffixes as a sum of elements" do
|
563
|
-
Timecode.parse("1h 4f").to_s.must_equal '01:00:00:04'
|
564
|
-
Timecode.parse("4f 1h").to_s.must_equal '01:00:00:04'
|
565
|
-
Timecode.parse("29f 1h").to_s.must_equal '01:00:01:04'
|
566
|
-
Timecode.parse("29f \n\n\n\n\n\ 1h").to_s.must_equal '01:00:01:04'
|
567
|
-
end
|
568
|
-
|
569
|
-
it "parse a number of digits as timecode" do
|
570
|
-
Timecode.parse("00000001").to_s.must_equal "00:00:00:01"
|
571
|
-
Timecode.parse("1").to_s.must_equal "00:00:00:01"
|
572
|
-
Timecode.parse("10").to_s.must_equal "00:00:00:10"
|
573
|
-
end
|
574
|
-
|
575
|
-
it "truncate a large number to the parseable length" do
|
576
|
-
Timecode.parse("1000000000000000001").to_s.must_equal "10:00:00:00"
|
577
|
-
end
|
578
|
-
|
579
|
-
it "left-pad a large number to give proper TC" do
|
580
|
-
Timecode.parse("123456", 57).to_s.must_equal "00:12:34:56"
|
581
|
-
end
|
582
|
-
|
583
|
-
it "parse timecode with fractional second instead of frames" do
|
584
|
-
fraction = "00:00:07.1"
|
585
|
-
tc = Timecode.parse_with_fractional_seconds(fraction, 10)
|
586
|
-
tc.to_s.must_equal "00:00:07:01"
|
587
|
-
|
588
|
-
fraction = "00:00:07.5"
|
589
|
-
tc = Timecode.parse_with_fractional_seconds(fraction, 10)
|
590
|
-
tc.to_s.must_equal "00:00:07:05"
|
591
|
-
|
592
|
-
fraction = "00:00:07.04"
|
593
|
-
tc = Timecode.parse_with_fractional_seconds(fraction, 12.5)
|
594
|
-
tc.to_s.must_equal "00:00:07:00"
|
595
|
-
|
596
|
-
fraction = "00:00:07.16"
|
597
|
-
tc = Timecode.parse_with_fractional_seconds(fraction, 12.5)
|
598
|
-
tc.to_s.must_equal "00:00:07:02"
|
599
|
-
end
|
600
|
-
|
601
|
-
it "reports DF timecode" do
|
602
|
-
df_tc = "00:00:00;01"
|
603
|
-
Timecode.parse(df_tc, 29.97).drop?.must_equal true
|
604
|
-
end
|
605
|
-
|
606
|
-
it "raise on improper format" do
|
607
|
-
lambda { Timecode.parse("Meaningless nonsense", 25) }.must_raise Timecode::CannotParse
|
608
|
-
lambda { Timecode.parse("", 25) }.must_raise Timecode::CannotParse
|
609
|
-
end
|
610
|
-
|
611
|
-
it "raise on empty argument" do
|
612
|
-
lambda { Timecode.parse(" \n\n ", 25) }.must_raise Timecode::CannotParse
|
613
|
-
end
|
614
|
-
|
615
|
-
it "properly handle 09 and 08 as part of complete TC pattern" do
|
616
|
-
Timecode.parse( "09:08:09:08", 25).total.must_equal 822233
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
|
-
describe "Timecode.soft_parse should" do
|
621
|
-
it "parse the timecode" do
|
622
|
-
Timecode.soft_parse('200').to_s.must_equal "00:00:02:00"
|
623
|
-
end
|
624
|
-
|
625
|
-
it "not raise on improper format and return zero TC instead" do
|
626
|
-
lambda do
|
627
|
-
tc = Timecode.soft_parse("Meaningless nonsense", 25)
|
628
|
-
tc.must_equal Timecode.new(0)
|
629
|
-
end.must_be_silent
|
630
|
-
end
|
631
|
-
end
|
632
|
-
|
633
|
-
describe 'Timecode#to_s' do
|
634
|
-
it 'formats 25 and 25 FPS timecodes uniformly' do
|
635
|
-
at25 = Timecode.parse("1h", 25)
|
636
|
-
at24 = Timecode.parse("1h", 24)
|
637
|
-
at25.to_s.must_equal "01:00:00:00"
|
638
|
-
at24.to_s.must_equal "01:00:00:00"
|
639
|
-
end
|
640
|
-
end
|
641
|
-
|
642
|
-
describe 'Timecode#inspect' do
|
643
|
-
it 'formats 25 and 25 FPS timecodes differently' do
|
644
|
-
at25 = Timecode.parse("1h", 25)
|
645
|
-
at24 = Timecode.parse("1h", 24)
|
646
|
-
at25.inspect.must_equal "#<Timecode:01:00:00:00 (90000F@25.00)>"
|
647
|
-
at24.inspect.must_equal "#<Timecode:01:00:00+00 (86400F@24.00)>"
|
648
|
-
end
|
649
|
-
end
|
650
|
-
|
651
|
-
describe "Timecode with unsigned integer conversions should" do
|
652
|
-
|
653
|
-
it "parse from a 4x4bits packed 32bit unsigned int" do
|
654
|
-
uint, tc = 87310853, Timecode.at(5,34,42,5)
|
655
|
-
Timecode.from_uint(uint).must_equal tc
|
656
|
-
end
|
657
|
-
|
658
|
-
it "properly convert itself back to 4x4 bits 32bit unsigned int" do
|
659
|
-
uint, tc = 87310853, Timecode.at(5,34,42,5)
|
660
|
-
tc.to_uint.must_equal uint
|
661
|
-
end
|
662
|
-
end
|