timecode 1.1.0 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/Manifest.txt +0 -1
- data/Rakefile +1 -5
- data/lib/timecode.rb +5 -5
- data/test/test_timecode.rb +101 -103
- metadata +62 -79
- data/SPECS.rdoc +0 -116
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 1.1.2 / 2011-10-11
|
2
|
+
|
3
|
+
* Fix warnings on Ruby 1.9.3
|
4
|
+
|
5
|
+
=== 1.1.1 / 2011-06-14
|
6
|
+
|
7
|
+
* Fix parsing of tick frame counts in Ruby 1.9 due to Array#to_s having different semantics
|
8
|
+
* Switch to bacon for specs.
|
9
|
+
|
1
10
|
=== 1.1.0 / 2011-02-16
|
2
11
|
|
3
12
|
* Added timecode with ticks support, used by CineCanvas (wolfgangw)
|
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -8,11 +8,7 @@ Hoe.spec('timecode') do |p|
|
|
8
8
|
p.extra_rdoc_files = FileList['*.rdoc']
|
9
9
|
|
10
10
|
p.developer('Julik', 'me@julik.nl')
|
11
|
-
p.extra_dev_deps = {"
|
11
|
+
p.extra_dev_deps = {"bacon" => ">=0"}
|
12
12
|
p.rubyforge_name = 'guerilla-di'
|
13
13
|
p.remote_rdoc_dir = 'timecode'
|
14
|
-
end
|
15
|
-
|
16
|
-
task "specs" do
|
17
|
-
`specrb test/* --rdox > SPECS.rdoc`
|
18
14
|
end
|
data/lib/timecode.rb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
# :mapping => [%w(source_tc_frames total), %w(tape_fps fps)]
|
13
13
|
|
14
14
|
class Timecode
|
15
|
-
VERSION = '1.1.
|
15
|
+
VERSION = '1.1.2'
|
16
16
|
|
17
17
|
include Comparable
|
18
18
|
|
@@ -146,8 +146,8 @@ class Timecode
|
|
146
146
|
raise RangeError, "There can be no more than 59 minutes, got #{mins}"
|
147
147
|
when secs > 59
|
148
148
|
raise RangeError, "There can be no more than 59 seconds, got #{secs}"
|
149
|
-
when frames > (with_fps -1)
|
150
|
-
raise RangeError, "There can be no more than #{with_fps -1} frames @#{with_fps}, got #{frames}"
|
149
|
+
when frames > (with_fps - 1)
|
150
|
+
raise RangeError, "There can be no more than #{with_fps - 1} frames @#{with_fps}, got #{frames}"
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -170,7 +170,7 @@ class Timecode
|
|
170
170
|
# used by CineCanvas systems
|
171
171
|
def parse_with_ticks(tc_with_ticks, fps = DEFAULT_FPS)
|
172
172
|
ticks_expr = /(\d{3})$/
|
173
|
-
num_ticks = tc_with_ticks.scan(ticks_expr).
|
173
|
+
num_ticks = tc_with_ticks.scan(ticks_expr).join.to_i
|
174
174
|
|
175
175
|
raise RangeError, "Invalid tick count #{num_ticks}" if num_ticks > 249
|
176
176
|
|
@@ -337,7 +337,7 @@ class Timecode
|
|
337
337
|
# Get the number of times a passed timecode fits into this time span (if performed with Timecode) or
|
338
338
|
# a Timecode that multiplied by arg will give this one
|
339
339
|
def /(arg)
|
340
|
-
arg.is_a?(Timecode) ? (@total / arg.total) : self.class.new(@total /arg, @fps)
|
340
|
+
arg.is_a?(Timecode) ? (@total / arg.total) : self.class.new(@total / arg, @fps)
|
341
341
|
end
|
342
342
|
|
343
343
|
# Timecodes can be compared to each other
|
data/test/test_timecode.rb
CHANGED
@@ -1,90 +1,88 @@
|
|
1
|
-
require 'test/unit'
|
2
1
|
require 'rubygems'
|
3
|
-
require '
|
2
|
+
require 'bacon'
|
4
3
|
|
5
|
-
require File.dirname(__FILE__) + '/../lib/timecode'
|
4
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../lib/timecode'
|
6
5
|
|
7
|
-
|
8
|
-
context "Timecode.new should" do
|
6
|
+
describe "Timecode.new should" do
|
9
7
|
|
10
|
-
|
8
|
+
it "should instantiate from int" do
|
11
9
|
tc = Timecode.new(10)
|
12
10
|
tc.should.be.kind_of Timecode
|
13
11
|
tc.total.should.equal 10
|
14
12
|
end
|
15
13
|
|
16
|
-
|
14
|
+
it "should always coerce FPS to float" do
|
17
15
|
Timecode.new(10, 24).fps.should.be.kind_of(Float)
|
18
16
|
Timecode.new(10, 25.0).fps.should.be.kind_of(Float)
|
19
17
|
end
|
20
18
|
|
21
|
-
|
19
|
+
it "should create a zero TC with no arguments" do
|
22
20
|
Timecode.new(nil).should.be.zero?
|
23
21
|
end
|
24
22
|
|
25
|
-
|
23
|
+
it "should accept full string SMPTE timecode as well" do
|
26
24
|
Timecode.new("00:25:30:10", 25).should.equal Timecode.parse("00:25:30:10")
|
27
25
|
end
|
28
26
|
|
29
27
|
end
|
30
28
|
|
31
|
-
|
29
|
+
describe "Timecode.validate_atoms! should" do
|
32
30
|
|
33
|
-
|
31
|
+
it "should disallow more than 99 hrs" do
|
34
32
|
lambda{ Timecode.validate_atoms!(99,0,0,0, 25) }.should.not.raise
|
35
33
|
lambda{ Timecode.validate_atoms!(100,0,0,0, 25) }.should.raise(Timecode::RangeError)
|
36
34
|
end
|
37
35
|
|
38
|
-
|
36
|
+
it "should disallow more than 59 minutes" do
|
39
37
|
lambda{ Timecode.validate_atoms!(1,60,0,0, 25) }.should.raise(Timecode::RangeError)
|
40
38
|
end
|
41
39
|
|
42
|
-
|
40
|
+
it "should disallow more than 59 seconds" do
|
43
41
|
lambda{ Timecode.validate_atoms!(1,0,60,0, 25) }.should.raise(Timecode::RangeError)
|
44
42
|
end
|
45
43
|
|
46
|
-
|
44
|
+
it "should disallow more frames than what the framerate permits" do
|
47
45
|
lambda{ Timecode.validate_atoms!(1,0,45,25, 25) }.should.raise(Timecode::RangeError)
|
48
46
|
lambda{ Timecode.validate_atoms!(1,0,45,32, 30) }.should.raise(Timecode::RangeError)
|
49
47
|
end
|
50
48
|
|
51
|
-
|
49
|
+
it "should pass validation with usable values" do
|
52
50
|
lambda{ Timecode.validate_atoms!(20, 20, 10, 5, 25)}.should.not.raise
|
53
51
|
end
|
54
52
|
end
|
55
53
|
|
56
|
-
|
54
|
+
describe "Timecode.at should" do
|
57
55
|
|
58
|
-
|
56
|
+
it "should disallow more than 99 hrs" do
|
59
57
|
lambda{ Timecode.at(99,0,0,0) }.should.not.raise
|
60
58
|
lambda{ Timecode.at(100,0,0,0) }.should.raise(Timecode::RangeError)
|
61
59
|
end
|
62
60
|
|
63
|
-
|
61
|
+
it "should disallow more than 59 minutes" do
|
64
62
|
lambda{ Timecode.at(1,60,0,0) }.should.raise(Timecode::RangeError)
|
65
63
|
end
|
66
64
|
|
67
|
-
|
65
|
+
it "should disallow more than 59 seconds" do
|
68
66
|
lambda{ Timecode.at(1,0,60,0) }.should.raise(Timecode::RangeError)
|
69
67
|
end
|
70
68
|
|
71
|
-
|
69
|
+
it "should disallow more frames than what the framerate permits" do
|
72
70
|
lambda{ Timecode.at(1,0,60,25, 25) }.should.raise(Timecode::RangeError)
|
73
71
|
lambda{ Timecode.at(1,0,60,32, 30) }.should.raise(Timecode::RangeError)
|
74
72
|
end
|
75
73
|
|
76
|
-
|
74
|
+
it "should propery accept usable values" do
|
77
75
|
Timecode.at(20, 20, 10, 5).to_s.should.equal "20:20:10:05"
|
78
76
|
end
|
79
77
|
end
|
80
78
|
|
81
|
-
|
82
|
-
|
79
|
+
describe "A new Timecode object should" do
|
80
|
+
it "should be frozen" do
|
83
81
|
Timecode.new(10).should.be.frozen
|
84
82
|
end
|
85
83
|
end
|
86
84
|
|
87
|
-
|
85
|
+
describe "An existing Timecode should" do
|
88
86
|
|
89
87
|
before do
|
90
88
|
@five_seconds = Timecode.new(5*25, 25)
|
@@ -92,47 +90,47 @@ context "An existing Timecode should" do
|
|
92
90
|
@film_tc = Timecode.new(@one_and_a_half_film, 24)
|
93
91
|
end
|
94
92
|
|
95
|
-
|
93
|
+
it "should report that the framerates are in delta" do
|
96
94
|
tc = Timecode.new(1)
|
97
95
|
tc.framerate_in_delta(25.0000000000000001, 25.0000000000000003).should.equal(true)
|
98
96
|
end
|
99
97
|
|
100
|
-
|
98
|
+
it "should validate equality based on delta" do
|
101
99
|
t1, t2 = Timecode.new(10, 25.0000000000000000000000000001), Timecode.new(10, 25.0000000000000000000000000002)
|
102
100
|
t1.should.equal(t2)
|
103
101
|
end
|
104
102
|
|
105
|
-
|
103
|
+
it "should report total as it's to_i" do
|
106
104
|
Timecode.new(10).to_i.should.equal(10)
|
107
105
|
end
|
108
106
|
|
109
|
-
|
107
|
+
it "should coerce itself to int" do
|
110
108
|
(10 + Timecode.new(2)).should.equal 12
|
111
109
|
end
|
112
110
|
|
113
|
-
|
111
|
+
it "should support hours" do
|
114
112
|
@five_seconds.should.respond_to :hours
|
115
113
|
@five_seconds.hours.should.equal 0
|
116
114
|
@film_tc.hours.should.equal 1
|
117
115
|
end
|
118
116
|
|
119
|
-
|
117
|
+
it "should support minutes" do
|
120
118
|
@five_seconds.should.respond_to :minutes
|
121
119
|
@five_seconds.minutes.should.equal 0
|
122
120
|
@film_tc.minutes.should.equal 30
|
123
121
|
end
|
124
122
|
|
125
|
-
|
123
|
+
it "should support seconds" do
|
126
124
|
@five_seconds.should.respond_to :seconds
|
127
125
|
@five_seconds.seconds.should.equal 5
|
128
126
|
@film_tc.seconds.should.equal 0
|
129
127
|
end
|
130
128
|
|
131
|
-
|
129
|
+
it "should support frames" do
|
132
130
|
@film_tc.frames.should.equal 0
|
133
131
|
end
|
134
132
|
|
135
|
-
|
133
|
+
it "should report frame_interval as a float" do
|
136
134
|
tc = Timecode.new(10)
|
137
135
|
tc.should.respond_to :frame_interval
|
138
136
|
|
@@ -141,45 +139,45 @@ context "An existing Timecode should" do
|
|
141
139
|
tc.frame_interval.should.be.close 0.03333, 0.0001
|
142
140
|
end
|
143
141
|
|
144
|
-
|
142
|
+
it "should be comparable" do
|
145
143
|
(Timecode.new(10) < Timecode.new(9)).should.equal false
|
146
144
|
(Timecode.new(9) < Timecode.new(10)).should.equal true
|
147
145
|
Timecode.new(9).should.equal Timecode.new(9)
|
148
146
|
end
|
149
147
|
|
150
|
-
|
148
|
+
it "should raise on comparison of incompatible timecodes" do
|
151
149
|
lambda { Timecode.new(10, 10) < Timecode.new(10, 20)}.should.raise(Timecode::WrongFramerate)
|
152
150
|
end
|
153
151
|
end
|
154
152
|
|
155
|
-
|
156
|
-
|
153
|
+
describe "A Timecode of zero should" do
|
154
|
+
it "should properly respond to zero?" do
|
157
155
|
Timecode.new(0).should.respond_to :zero?
|
158
156
|
Timecode.new(0).should.be.zero
|
159
157
|
Timecode.new(1).should.not.be.zero
|
160
158
|
end
|
161
159
|
end
|
162
160
|
|
163
|
-
|
164
|
-
|
161
|
+
describe "Timecode.from_seconds should" do
|
162
|
+
it "should properly process this specific case for a float framerate" do
|
165
163
|
float_secs = 89.99165971643036
|
166
164
|
float_fps = 23.9898
|
167
165
|
lambda{ Timecode.from_seconds(float_secs, float_fps) }.should.not.raise
|
168
166
|
end
|
169
167
|
end
|
170
168
|
|
171
|
-
|
172
|
-
|
169
|
+
describe "Timecode#to_seconds should" do
|
170
|
+
it "should return a float" do
|
173
171
|
Timecode.new(0).to_seconds.should.be.kind_of Float
|
174
172
|
end
|
175
173
|
|
176
|
-
|
174
|
+
it "should return the value in seconds" do
|
177
175
|
fps = 24
|
178
176
|
secs = 126.3
|
179
177
|
Timecode.new(fps * secs, fps).to_seconds.should.be.close 126.3, 0.1
|
180
178
|
end
|
181
179
|
|
182
|
-
|
180
|
+
it "should properly roundtrip a value via Timecode.from_seconds" do
|
183
181
|
secs_in = 19.76
|
184
182
|
from_secs = Timecode.from_seconds(19.76, 25.0)
|
185
183
|
from_secs.total.should.equal 494
|
@@ -187,43 +185,43 @@ context "Timecode#to_seconds should" do
|
|
187
185
|
end
|
188
186
|
end
|
189
187
|
|
190
|
-
|
191
|
-
|
188
|
+
describe "An existing Timecode on inspection should" do
|
189
|
+
it "should properly present himself via inspect" do
|
192
190
|
Timecode.new(10, 25).inspect.should.equal "#<Timecode:00:00:00:10 (10F@25.00)>"
|
193
191
|
Timecode.new(10, 12).inspect.should.equal "#<Timecode:00:00:00:10 (10F@12.00)>"
|
194
192
|
end
|
195
193
|
|
196
|
-
|
194
|
+
it "should properly print itself" do
|
197
195
|
Timecode.new(5, 25).to_s.should.equal "00:00:00:05"
|
198
196
|
end
|
199
197
|
end
|
200
198
|
|
201
|
-
|
202
|
-
|
199
|
+
describe "An existing Timecode compared by adjacency" do
|
200
|
+
it "should properly detect an adjacent timecode to the left" do
|
203
201
|
Timecode.new(10).should.be.adjacent_to(Timecode.new(9))
|
204
202
|
end
|
205
203
|
|
206
|
-
|
204
|
+
it "should properly detect an adjacent timecode to the right" do
|
207
205
|
Timecode.new(10).should.be.adjacent_to(Timecode.new(11))
|
208
206
|
end
|
209
207
|
|
210
208
|
end
|
211
209
|
|
212
|
-
|
213
|
-
|
210
|
+
describe "A Timecode on conversion should" do
|
211
|
+
it "should copy itself with a different framerate" do
|
214
212
|
tc = Timecode.new(40,25)
|
215
213
|
at24 = tc.convert(24)
|
216
214
|
at24.total.should.equal 40
|
217
215
|
end
|
218
216
|
end
|
219
217
|
|
220
|
-
|
221
|
-
|
218
|
+
describe "An existing Timecode used within ranges should" do
|
219
|
+
it "should properly provide successive value that is one frame up" do
|
222
220
|
Timecode.new(10).succ.total.should.equal 11
|
223
221
|
Timecode.new(22, 45).succ.should.equal Timecode.new(23, 45)
|
224
222
|
end
|
225
223
|
|
226
|
-
|
224
|
+
it "should work as a range member" do
|
227
225
|
r = Timecode.new(10)...Timecode.new(20)
|
228
226
|
r.to_a.length.should.equal 10
|
229
227
|
r.to_a[4].should.equal Timecode.new(14)
|
@@ -231,74 +229,74 @@ context "An existing Timecode used within ranges should" do
|
|
231
229
|
|
232
230
|
end
|
233
231
|
|
234
|
-
|
235
|
-
|
232
|
+
describe "A Timecode on conversion should" do
|
233
|
+
it "should copy itself with a different framerate" do
|
236
234
|
tc = Timecode.new(40,25)
|
237
235
|
at24 = tc.convert(24)
|
238
236
|
at24.total.should.equal 40
|
239
237
|
end
|
240
238
|
end
|
241
239
|
|
242
|
-
|
240
|
+
describe "A Timecode on calculations should" do
|
243
241
|
|
244
|
-
|
242
|
+
it "should support addition" do
|
245
243
|
a, b = Timecode.new(24, 25.000000000000001), Timecode.new(22, 25.000000000000002)
|
246
244
|
(a + b).should.equal Timecode.new(24 + 22, 25.000000000000001)
|
247
245
|
end
|
248
246
|
|
249
|
-
|
247
|
+
it "should should raise on addition if framerates do not match" do
|
250
248
|
lambda{ Timecode.new(10, 25) + Timecode.new(10, 30) }.should.raise(Timecode::WrongFramerate)
|
251
249
|
end
|
252
250
|
|
253
|
-
|
251
|
+
it "should when added with an integer instead calculate on total" do
|
254
252
|
(Timecode.new(5) + 5).should.equal(Timecode.new(10))
|
255
253
|
end
|
256
254
|
|
257
|
-
|
255
|
+
it "should support subtraction" do
|
258
256
|
a, b = Timecode.new(10), Timecode.new(4)
|
259
257
|
(a - b).should.equal Timecode.new(6)
|
260
258
|
end
|
261
259
|
|
262
|
-
|
260
|
+
it "should on subtraction of an integer instead calculate on total" do
|
263
261
|
(Timecode.new(15) - 5).should.equal Timecode.new(10)
|
264
262
|
end
|
265
263
|
|
266
|
-
|
264
|
+
it "should raise when subtracting a Timecode with a different framerate" do
|
267
265
|
lambda { Timecode.new(10, 25) - Timecode.new(10, 30) }.should.raise(Timecode::WrongFramerate)
|
268
266
|
end
|
269
267
|
|
270
|
-
|
268
|
+
it "should support multiplication" do
|
271
269
|
(Timecode.new(10) * 10).should.equal(Timecode.new(100))
|
272
270
|
end
|
273
271
|
|
274
|
-
|
272
|
+
it "should raise when the resultig Timecode is negative" do
|
275
273
|
lambda { Timecode.new(10) * -200 }.should.raise(Timecode::RangeError)
|
276
274
|
end
|
277
275
|
|
278
|
-
|
276
|
+
it "should return a Timecode when divided by an Integer" do
|
279
277
|
v = Timecode.new(200) / 20
|
280
278
|
v.should.be.kind_of(Timecode)
|
281
279
|
v.should.equal Timecode.new(10)
|
282
280
|
end
|
283
281
|
|
284
|
-
|
282
|
+
it "should return a number when divided by another Timecode" do
|
285
283
|
v = Timecode.new(200) / Timecode.new(20)
|
286
284
|
v.should.be.kind_of(Numeric)
|
287
285
|
v.should.equal 10
|
288
286
|
end
|
289
287
|
end
|
290
288
|
|
291
|
-
|
289
|
+
describe "A Timecode used with fractional number of seconds" do
|
292
290
|
|
293
|
-
|
294
|
-
tc = Timecode.new(100 -1, fps = 25)
|
291
|
+
it "should should properly return fractional seconds" do
|
292
|
+
tc = Timecode.new(100 - 1, fps = 25)
|
295
293
|
tc.frames.should.equal 24
|
296
294
|
|
297
295
|
tc.with_frames_as_fraction.should.equal "00:00:03.96"
|
298
296
|
tc.with_fractional_seconds.should.equal "00:00:03.96"
|
299
297
|
end
|
300
298
|
|
301
|
-
|
299
|
+
it "should properly translate to frames when instantiated from fractional seconds" do
|
302
300
|
fraction = 7.1
|
303
301
|
tc = Timecode.from_seconds(fraction, 10)
|
304
302
|
tc.to_s.should.equal "00:00:07:01"
|
@@ -314,18 +312,18 @@ context "A Timecode used with fractional number of seconds" do
|
|
314
312
|
|
315
313
|
end
|
316
314
|
|
317
|
-
|
315
|
+
describe "A custom Timecode descendant should" do
|
318
316
|
class CustomTC < Timecode; end
|
319
317
|
|
320
|
-
|
318
|
+
it "should properly classify on parse" do
|
321
319
|
CustomTC.parse("001").should.be.kind_of CustomTC
|
322
320
|
end
|
323
321
|
|
324
|
-
|
322
|
+
it "should properly classify on at" do
|
325
323
|
CustomTC.at(10,10,10,10).should.be.kind_of CustomTC
|
326
324
|
end
|
327
325
|
|
328
|
-
|
326
|
+
it "should properly classify on calculations" do
|
329
327
|
computed = CustomTC.parse("10h") + Timecode.new(10)
|
330
328
|
computed.should.be.kind_of CustomTC
|
331
329
|
|
@@ -341,26 +339,26 @@ context "A custom Timecode descendant should" do
|
|
341
339
|
|
342
340
|
end
|
343
341
|
|
344
|
-
|
342
|
+
describe "Timecode.parse should" do
|
345
343
|
|
346
|
-
|
344
|
+
it "should handle complete SMPTE timecode" do
|
347
345
|
simple_tc = "00:10:34:10"
|
348
346
|
Timecode.parse(simple_tc).to_s.should.equal(simple_tc)
|
349
347
|
end
|
350
348
|
|
351
|
-
|
349
|
+
it "should handle complete SMPTE timecode with plus for 24 frames per second" do
|
352
350
|
simple_tc = "00:10:34+10"
|
353
351
|
p = Timecode.parse(simple_tc)
|
354
352
|
p.to_s.should.equal(simple_tc)
|
355
353
|
p.fps.should.equal 24
|
356
354
|
end
|
357
355
|
|
358
|
-
|
356
|
+
it "should handle timecode with fractional seconds" do
|
359
357
|
tc = Timecode.parse("10:10:10.2", 25)
|
360
358
|
tc.to_s.should.equal "10:10:10:05"
|
361
359
|
end
|
362
360
|
|
363
|
-
|
361
|
+
it "should handle timecode with ticks" do
|
364
362
|
tc = Timecode.parse("10:10:10:103", 25)
|
365
363
|
tc.to_s.should.equal "10:10:10:10"
|
366
364
|
|
@@ -368,69 +366,69 @@ context "Timecode.parse should" do
|
|
368
366
|
tc.to_s.should.equal "10:10:10:24"
|
369
367
|
end
|
370
368
|
|
371
|
-
|
369
|
+
it "should raise when there are more than 249 ticks" do
|
372
370
|
lambda {
|
373
371
|
tc = Timecode.parse("10:10:10:250", 25)
|
374
372
|
}.should.raise(Timecode::RangeError)
|
375
373
|
end
|
376
374
|
|
377
|
-
|
375
|
+
it "should handle timecode with fractional seconds with spaces at start and end" do
|
378
376
|
tc = Timecode.parse(" 00:00:01.040 ")
|
379
377
|
tc.to_s.should.equal "00:00:01:01"
|
380
378
|
end
|
381
379
|
|
382
380
|
# I am commenting this one out for now, these were present in some odd subtitle file.
|
383
381
|
# What we probably need is a way for Timecode to "extract" timecodes from a chunk of text.
|
384
|
-
#
|
382
|
+
# it "should handle timecode with fractional seconds with weirdo UTF spaces at start and end" do
|
385
383
|
# tc = Timecode.parse("00:00:01.040")
|
386
384
|
# tc.to_s.should.equal "00:00:01:01"
|
387
385
|
# end
|
388
386
|
|
389
|
-
|
387
|
+
it "should parse a row of numbers as parts of a timecode starting from the right" do
|
390
388
|
Timecode.parse("10").should.equal Timecode.new(10)
|
391
389
|
Timecode.parse("210").should.equal Timecode.new(60)
|
392
390
|
Timecode.parse("10101010").to_s.should.equal "10:10:10:10"
|
393
391
|
end
|
394
392
|
|
395
|
-
|
393
|
+
it "should parse a number with f suffix as frames" do
|
396
394
|
Timecode.parse("60f").should.equal Timecode.new(60)
|
397
395
|
end
|
398
396
|
|
399
|
-
|
397
|
+
it "should parse a number with s suffix as seconds" do
|
400
398
|
Timecode.parse("2s", 25).should.equal Timecode.new(50, 25)
|
401
399
|
Timecode.parse("2s", 30).should.equal Timecode.new(60, 30)
|
402
400
|
end
|
403
401
|
|
404
|
-
|
402
|
+
it "should parse a number with m suffix as minutes" do
|
405
403
|
Timecode.parse("3m").should.equal Timecode.new(25 * 60 * 3)
|
406
404
|
end
|
407
405
|
|
408
|
-
|
406
|
+
it "should parse a number with h suffix as hours" do
|
409
407
|
Timecode.parse("3h").should.equal Timecode.new(25 * 60 * 60 * 3)
|
410
408
|
end
|
411
409
|
|
412
|
-
|
410
|
+
it "should parse different suffixes as a sum of elements" do
|
413
411
|
Timecode.parse("1h 4f").to_s.should.equal '01:00:00:04'
|
414
412
|
Timecode.parse("4f 1h").to_s.should.equal '01:00:00:04'
|
415
413
|
Timecode.parse("29f 1h").to_s.should.equal '01:00:01:04'
|
416
414
|
Timecode.parse("29f \n\n\n\n\n\ 1h").to_s.should.equal '01:00:01:04'
|
417
415
|
end
|
418
416
|
|
419
|
-
|
417
|
+
it "should parse a number of digits as timecode" do
|
420
418
|
Timecode.parse("00000001").to_s.should.equal "00:00:00:01"
|
421
419
|
Timecode.parse("1").to_s.should.equal "00:00:00:01"
|
422
420
|
Timecode.parse("10").to_s.should.equal "00:00:00:10"
|
423
421
|
end
|
424
422
|
|
425
|
-
|
423
|
+
it "should truncate a large number to the parseable length" do
|
426
424
|
Timecode.parse("1000000000000000001").to_s.should.equal "10:00:00:00"
|
427
425
|
end
|
428
426
|
|
429
|
-
|
427
|
+
it "should left-pad a large number to give proper TC" do
|
430
428
|
Timecode.parse("123456", 57).to_s.should.equal "00:12:34:56"
|
431
429
|
end
|
432
430
|
|
433
|
-
|
431
|
+
it "should parse timecode with fractional second instead of frames" do
|
434
432
|
fraction = "00:00:07.1"
|
435
433
|
tc = Timecode.parse_with_fractional_seconds(fraction, 10)
|
436
434
|
tc.to_s.should.equal "00:00:07:01"
|
@@ -448,31 +446,31 @@ context "Timecode.parse should" do
|
|
448
446
|
tc.to_s.should.equal "00:00:07:02"
|
449
447
|
end
|
450
448
|
|
451
|
-
|
449
|
+
it "should raise when trying to parse DF timecode" do
|
452
450
|
df_tc = "00:00:00;01"
|
453
451
|
lambda { Timecode.parse(df_tc)}.should.raise(Timecode::Error)
|
454
452
|
end
|
455
453
|
|
456
|
-
|
454
|
+
it "should raise on improper format" do
|
457
455
|
lambda { Timecode.parse("Meaningless nonsense", 25) }.should.raise Timecode::CannotParse
|
458
456
|
lambda { Timecode.parse("", 25) }.should.raise Timecode::CannotParse
|
459
457
|
end
|
460
458
|
|
461
|
-
|
459
|
+
it "should raise on empty argument" do
|
462
460
|
lambda { Timecode.parse(" \n\n ", 25) }.should.raise Timecode::CannotParse
|
463
461
|
end
|
464
462
|
|
465
|
-
|
463
|
+
it "should properly handle 09 and 08 as part of complete TC pattern" do
|
466
464
|
Timecode.parse( "09:08:09:08", 25).total.should.equal 822233
|
467
465
|
end
|
468
466
|
end
|
469
467
|
|
470
|
-
|
471
|
-
|
468
|
+
describe "Timecode.soft_parse should" do
|
469
|
+
it "should parse the timecode" do
|
472
470
|
Timecode.soft_parse('200').to_s.should.equal "00:00:02:00"
|
473
471
|
end
|
474
472
|
|
475
|
-
|
473
|
+
it "should not raise on improper format and return zero TC instead" do
|
476
474
|
lambda do
|
477
475
|
tc = Timecode.soft_parse("Meaningless nonsense", 25)
|
478
476
|
tc.should.be.zero?
|
@@ -481,14 +479,14 @@ context "Timecode.soft_parse should" do
|
|
481
479
|
end
|
482
480
|
|
483
481
|
|
484
|
-
|
482
|
+
describe "Timecode with unsigned integer conversions should" do
|
485
483
|
|
486
|
-
|
484
|
+
it "should parse from a 4x4bits packed 32bit unsigned int" do
|
487
485
|
uint, tc = 87310853, Timecode.at(5,34,42,5)
|
488
486
|
Timecode.from_uint(uint).should.equal tc
|
489
487
|
end
|
490
488
|
|
491
|
-
|
489
|
+
it "should properly convert itself back to 4x4 bits 32bit unsigned int" do
|
492
490
|
uint, tc = 87310853, Timecode.at(5,34,42,5)
|
493
491
|
tc.to_uint.should.equal uint
|
494
492
|
end
|
metadata
CHANGED
@@ -1,109 +1,92 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: timecode
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.2
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 1.1.0
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Julik
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
name: test-spec
|
23
|
-
prerelease: false
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
12
|
+
date: 2011-11-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bacon
|
16
|
+
requirement: &1348040 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :development
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: hoe
|
37
23
|
prerelease: false
|
38
|
-
|
24
|
+
version_requirements: *1348040
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
requirement: &1347600 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
segments:
|
45
|
-
- 2
|
46
|
-
- 9
|
47
|
-
- 1
|
48
|
-
version: 2.9.1
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.12'
|
49
33
|
type: :development
|
50
|
-
|
51
|
-
|
52
|
-
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *1347600
|
36
|
+
description: !binary |-
|
37
|
+
VmFsdWUgY2xhc3MgZm9yIFNNUFRFIHRpbWVjb2RlIGluZm9ybWF0aW9u
|
38
|
+
email:
|
53
39
|
- me@julik.nl
|
54
40
|
executables: []
|
55
|
-
|
56
41
|
extensions: []
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
-
|
61
|
-
|
62
|
-
- SPECS.rdoc
|
63
|
-
files:
|
64
|
-
- .DS_Store
|
65
|
-
- History.txt
|
66
|
-
- Manifest.txt
|
42
|
+
extra_rdoc_files:
|
43
|
+
- !binary |-
|
44
|
+
SGlzdG9yeS50eHQ=
|
45
|
+
- !binary |-
|
46
|
+
TWFuaWZlc3QudHh0
|
67
47
|
- README.rdoc
|
68
|
-
|
69
|
-
-
|
70
|
-
|
71
|
-
-
|
48
|
+
files:
|
49
|
+
- !binary |-
|
50
|
+
LkRTX1N0b3Jl
|
51
|
+
- !binary |-
|
52
|
+
SGlzdG9yeS50eHQ=
|
53
|
+
- !binary |-
|
54
|
+
TWFuaWZlc3QudHh0
|
55
|
+
- !binary |-
|
56
|
+
UkVBRE1FLnJkb2M=
|
57
|
+
- !binary |-
|
58
|
+
UmFrZWZpbGU=
|
59
|
+
- !binary |-
|
60
|
+
bGliL3RpbWVjb2RlLnJi
|
61
|
+
- !binary |-
|
62
|
+
dGVzdC90ZXN0X3RpbWVjb2RlLnJi
|
72
63
|
- .gemtest
|
73
|
-
has_rdoc: true
|
74
64
|
homepage: http://guerilla-di.org/timecode
|
75
65
|
licenses: []
|
76
|
-
|
77
66
|
post_install_message:
|
78
|
-
rdoc_options:
|
67
|
+
rdoc_options:
|
79
68
|
- --main
|
80
69
|
- README.rdoc
|
81
|
-
require_paths:
|
70
|
+
require_paths:
|
82
71
|
- lib
|
83
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
73
|
none: false
|
85
|
-
requirements:
|
86
|
-
- -
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
|
89
|
-
|
90
|
-
- 0
|
91
|
-
version: "0"
|
92
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
79
|
none: false
|
94
|
-
requirements:
|
95
|
-
- -
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
|
98
|
-
segments:
|
99
|
-
- 0
|
100
|
-
version: "0"
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
101
84
|
requirements: []
|
102
|
-
|
103
85
|
rubyforge_project: guerilla-di
|
104
|
-
rubygems_version: 1.
|
86
|
+
rubygems_version: 1.8.5
|
105
87
|
signing_key:
|
106
88
|
specification_version: 3
|
107
|
-
summary:
|
108
|
-
|
89
|
+
summary: !binary |-
|
90
|
+
VmFsdWUgY2xhc3MgZm9yIFNNUFRFIHRpbWVjb2RlIGluZm9ybWF0aW9u
|
91
|
+
test_files:
|
109
92
|
- test/test_timecode.rb
|
data/SPECS.rdoc
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
|
2
|
-
== Timecode.new should
|
3
|
-
* instantiate from int
|
4
|
-
* always coerce FPS to float
|
5
|
-
* create a zero TC with no arguments
|
6
|
-
* accept full string SMPTE timecode as well
|
7
|
-
|
8
|
-
== Timecode.validate_atoms! should
|
9
|
-
* disallow more than 99 hrs
|
10
|
-
* disallow more than 59 minutes
|
11
|
-
* disallow more than 59 seconds
|
12
|
-
* disallow more frames than what the framerate permits
|
13
|
-
* pass validation with usable values
|
14
|
-
|
15
|
-
== Timecode.at should
|
16
|
-
* disallow more than 99 hrs
|
17
|
-
* disallow more than 59 minutes
|
18
|
-
* disallow more than 59 seconds
|
19
|
-
* disallow more frames than what the framerate permits
|
20
|
-
* propery accept usable values
|
21
|
-
|
22
|
-
== A new Timecode object should
|
23
|
-
* be frozen
|
24
|
-
|
25
|
-
== An existing Timecode should
|
26
|
-
* report that the framerates are in delta
|
27
|
-
* validate equality based on delta
|
28
|
-
* report total as it's to_i
|
29
|
-
* coerce itself to int
|
30
|
-
* support hours
|
31
|
-
* support minutes
|
32
|
-
* support seconds
|
33
|
-
* support frames
|
34
|
-
* report frame_interval as a float
|
35
|
-
* be comparable
|
36
|
-
* raise on comparison of incompatible timecodes
|
37
|
-
|
38
|
-
== A Timecode of zero should
|
39
|
-
* properly respond to zero?
|
40
|
-
|
41
|
-
== Timecode.from_seconds should
|
42
|
-
* properly process this specific case for a float framerate
|
43
|
-
|
44
|
-
== Timecode#to_seconds should
|
45
|
-
* return a float
|
46
|
-
* return the value in seconds
|
47
|
-
* properly roundtrip a value via Timecode.from_seconds
|
48
|
-
|
49
|
-
== An existing Timecode on inspection should
|
50
|
-
* properly present himself via inspect
|
51
|
-
* properly print itself
|
52
|
-
|
53
|
-
== An existing Timecode compared by adjacency
|
54
|
-
* properly detect an adjacent timecode to the left
|
55
|
-
* properly detect an adjacent timecode to the right
|
56
|
-
|
57
|
-
== A Timecode on conversion should
|
58
|
-
* copy itself with a different framerate
|
59
|
-
* copy itself with a different framerate
|
60
|
-
|
61
|
-
== An existing Timecode used within ranges should
|
62
|
-
* properly provide successive value that is one frame up
|
63
|
-
* work as a range member
|
64
|
-
|
65
|
-
== A Timecode on calculations should
|
66
|
-
* support addition
|
67
|
-
* should raise on addition if framerates do not match
|
68
|
-
* when added with an integer instead calculate on total
|
69
|
-
* support subtraction
|
70
|
-
* on subtraction of an integer instead calculate on total
|
71
|
-
* raise when subtracting a Timecode with a different framerate
|
72
|
-
* support multiplication
|
73
|
-
* raise when the resultig Timecode is negative
|
74
|
-
* return a Timecode when divided by an Integer
|
75
|
-
* return a number when divided by another Timecode
|
76
|
-
|
77
|
-
== A Timecode used with fractional number of seconds
|
78
|
-
* should properly return fractional seconds
|
79
|
-
* properly translate to frames when instantiated from fractional seconds
|
80
|
-
|
81
|
-
== A custom Timecode descendant should
|
82
|
-
* properly classify on parse
|
83
|
-
* properly classify on at
|
84
|
-
* properly classify on calculations
|
85
|
-
|
86
|
-
== Timecode.parse should
|
87
|
-
* handle complete SMPTE timecode
|
88
|
-
* handle complete SMPTE timecode with plus for 24 frames per second
|
89
|
-
* handle timecode with fractional seconds
|
90
|
-
* handle timecode with ticks
|
91
|
-
* raise when there are more than 249 ticks
|
92
|
-
* handle timecode with fractional seconds with spaces at start and end
|
93
|
-
* parse a row of numbers as parts of a timecode starting from the right
|
94
|
-
* parse a number with f suffix as frames
|
95
|
-
* parse a number with s suffix as seconds
|
96
|
-
* parse a number with m suffix as minutes
|
97
|
-
* parse a number with h suffix as hours
|
98
|
-
* parse different suffixes as a sum of elements
|
99
|
-
* parse a number of digits as timecode
|
100
|
-
* truncate a large number to the parseable length
|
101
|
-
* left-pad a large number to give proper TC
|
102
|
-
* parse timecode with fractional second instead of frames
|
103
|
-
* raise when trying to parse DF timecode
|
104
|
-
* raise on improper format
|
105
|
-
* raise on empty argument
|
106
|
-
* properly handle 09 and 08 as part of complete TC pattern
|
107
|
-
|
108
|
-
== Timecode.soft_parse should
|
109
|
-
* parse the timecode
|
110
|
-
* not raise on improper format and return zero TC instead
|
111
|
-
|
112
|
-
== Timecode with unsigned integer conversions should
|
113
|
-
* parse from a 4x4bits packed 32bit unsigned int
|
114
|
-
* properly convert itself back to 4x4 bits 32bit unsigned int
|
115
|
-
|
116
|
-
78 specifications (124 requirements), 0 failures
|