timecode 1.1.0 → 1.1.2
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.
- 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
|