titlekit 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +22 -0
  6. data/README.md +335 -0
  7. data/Rakefile +8 -0
  8. data/lib/titlekit/have.rb +90 -0
  9. data/lib/titlekit/job.rb +446 -0
  10. data/lib/titlekit/parsers/ass.rb +175 -0
  11. data/lib/titlekit/parsers/ass.treetop +72 -0
  12. data/lib/titlekit/parsers/srt.rb +139 -0
  13. data/lib/titlekit/parsers/srt.treetop +73 -0
  14. data/lib/titlekit/parsers/ssa.rb +201 -0
  15. data/lib/titlekit/parsers/ssa.treetop +72 -0
  16. data/lib/titlekit/specification.rb +131 -0
  17. data/lib/titlekit/utilities.rb +3 -0
  18. data/lib/titlekit/version.rb +3 -0
  19. data/lib/titlekit/want.rb +24 -0
  20. data/lib/titlekit.rb +9 -0
  21. data/spec/ass_spec.rb +113 -0
  22. data/spec/automatic_grouping/automatic_grouping_spec.rb +55 -0
  23. data/spec/automatic_grouping/dual_tracks/expected.srt +15 -0
  24. data/spec/automatic_grouping/dual_tracks/one.srt +11 -0
  25. data/spec/automatic_grouping/dual_tracks/out.srt +15 -0
  26. data/spec/automatic_grouping/dual_tracks/two.srt +11 -0
  27. data/spec/automatic_grouping/single_track/expected.srt +24 -0
  28. data/spec/automatic_grouping/single_track/one.srt +11 -0
  29. data/spec/automatic_grouping/single_track/out.srt +24 -0
  30. data/spec/automatic_grouping/single_track/two.srt +11 -0
  31. data/spec/encoding_detection/a/in.ass +0 -0
  32. data/spec/encoding_detection/b/in.srt +2389 -0
  33. data/spec/encoding_detection/b/out.srt +2389 -0
  34. data/spec/encoding_detection/c/in.srt +5320 -0
  35. data/spec/encoding_detection/c/out.srt +5320 -0
  36. data/spec/encoding_detection/encoding_detection_spec.rb +81 -0
  37. data/spec/files/ass/authentic.ass +0 -0
  38. data/spec/files/ass/hard.ass +37 -0
  39. data/spec/files/ass/simple.ass +28 -0
  40. data/spec/files/srt/authentic.srt +2708 -0
  41. data/spec/files/srt/coordinates.srt +13 -0
  42. data/spec/files/srt/simple.srt +12 -0
  43. data/spec/files/ssa/simple.ssa +26 -0
  44. data/spec/files/try/unsupported-output.try +0 -0
  45. data/spec/files/try/unsupported.try +7 -0
  46. data/spec/format_conversion/ass_srt/expected.srt +2327 -0
  47. data/spec/format_conversion/ass_srt/in.ass +485 -0
  48. data/spec/format_conversion/ass_srt/out.srt +2327 -0
  49. data/spec/format_conversion/format_conversion_spec.rb +112 -0
  50. data/spec/format_conversion/srt_ass/expected.ass +19 -0
  51. data/spec/format_conversion/srt_ass/in.srt +12 -0
  52. data/spec/format_conversion/srt_ass/out.ass +19 -0
  53. data/spec/format_conversion/srt_ssa/expected.ssa +19 -0
  54. data/spec/format_conversion/srt_ssa/in.srt +12 -0
  55. data/spec/format_conversion/srt_ssa/out.ssa +19 -0
  56. data/spec/format_conversion/ssa_srt/expected.srt +9 -0
  57. data/spec/format_conversion/ssa_srt/in.ssa +26 -0
  58. data/spec/format_conversion/ssa_srt/out.srt +9 -0
  59. data/spec/job_spec.rb +162 -0
  60. data/spec/simultaneous_subtitles/dual/ass/expected.ass +22 -0
  61. data/spec/simultaneous_subtitles/dual/ass/out.ass +22 -0
  62. data/spec/simultaneous_subtitles/dual/one.srt +11 -0
  63. data/spec/simultaneous_subtitles/dual/srt/expected.srt +27 -0
  64. data/spec/simultaneous_subtitles/dual/srt/out.srt +27 -0
  65. data/spec/simultaneous_subtitles/dual/ssa/expected.ssa +22 -0
  66. data/spec/simultaneous_subtitles/dual/ssa/out.ssa +22 -0
  67. data/spec/simultaneous_subtitles/dual/two.srt +11 -0
  68. data/spec/simultaneous_subtitles/simultaneous_subtitles_spec.rb +220 -0
  69. data/spec/simultaneous_subtitles/triple/ass/expected.ass +25 -0
  70. data/spec/simultaneous_subtitles/triple/ass/out.ass +25 -0
  71. data/spec/simultaneous_subtitles/triple/one.srt +11 -0
  72. data/spec/simultaneous_subtitles/triple/srt/expected.srt +55 -0
  73. data/spec/simultaneous_subtitles/triple/srt/out.srt +55 -0
  74. data/spec/simultaneous_subtitles/triple/ssa/expected.ssa +25 -0
  75. data/spec/simultaneous_subtitles/triple/ssa/out.ssa +25 -0
  76. data/spec/simultaneous_subtitles/triple/three.srt +11 -0
  77. data/spec/simultaneous_subtitles/triple/two.srt +11 -0
  78. data/spec/simultaneous_subtitles/triple_plus/ass/expected.ass +93 -0
  79. data/spec/simultaneous_subtitles/triple_plus/ass/out.ass +93 -0
  80. data/spec/simultaneous_subtitles/triple_plus/five.srt +11 -0
  81. data/spec/simultaneous_subtitles/triple_plus/four.srt +11 -0
  82. data/spec/simultaneous_subtitles/triple_plus/one.srt +11 -0
  83. data/spec/simultaneous_subtitles/triple_plus/six.srt +11 -0
  84. data/spec/simultaneous_subtitles/triple_plus/srt/expected.srt +149 -0
  85. data/spec/simultaneous_subtitles/triple_plus/srt/out.srt +149 -0
  86. data/spec/simultaneous_subtitles/triple_plus/ssa/expected.ssa +93 -0
  87. data/spec/simultaneous_subtitles/triple_plus/ssa/out.ssa +93 -0
  88. data/spec/simultaneous_subtitles/triple_plus/three.srt +11 -0
  89. data/spec/simultaneous_subtitles/triple_plus/two.srt +11 -0
  90. data/spec/spec_helper.rb +7 -0
  91. data/spec/specifications_spec.rb +138 -0
  92. data/spec/srt_spec.rb +134 -0
  93. data/spec/ssa_spec.rb +90 -0
  94. data/spec/timecode_correction/double_reference/expected.srt +13 -0
  95. data/spec/timecode_correction/double_reference/in.srt +12 -0
  96. data/spec/timecode_correction/double_reference/out.srt +13 -0
  97. data/spec/timecode_correction/framerate/expected.srt +5 -0
  98. data/spec/timecode_correction/framerate/in.srt +4 -0
  99. data/spec/timecode_correction/framerate/out.srt +5 -0
  100. data/spec/timecode_correction/framerate_plus_reference/expected.srt +13 -0
  101. data/spec/timecode_correction/framerate_plus_reference/in.srt +12 -0
  102. data/spec/timecode_correction/framerate_plus_reference/out.srt +13 -0
  103. data/spec/timecode_correction/single_reference/expected.srt +13 -0
  104. data/spec/timecode_correction/single_reference/in.srt +12 -0
  105. data/spec/timecode_correction/single_reference/out.srt +13 -0
  106. data/spec/timecode_correction/timecode_correction_spec.rb +124 -0
  107. data/spec/transcoding/gb2312-ascii/in.srt +12 -0
  108. data/spec/transcoding/iso-8859-1_utf-8/expected.srt +12 -0
  109. data/spec/transcoding/iso-8859-1_utf-8/in.srt +11 -0
  110. data/spec/transcoding/iso-8859-1_utf-8/out.srt +12 -0
  111. data/spec/transcoding/transcoding_spec.rb +116 -0
  112. data/spec/transcoding/utf-8_gbk/expected.srt +12 -0
  113. data/spec/transcoding/utf-8_gbk/in.srt +11 -0
  114. data/spec/transcoding/utf-8_gbk/out.srt +12 -0
  115. data/spec/transcoding/windows-1252_utf-8/expected.srt +12 -0
  116. data/spec/transcoding/windows-1252_utf-8/in.srt +11 -0
  117. data/spec/transcoding/windows-1252_utf-8/out.srt +12 -0
  118. data/titlekit.gemspec +28 -0
  119. metadata +313 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b36a1f0921cdaa8ccdc52e9947507e17fa15000
4
+ data.tar.gz: c9925463a03d50b1486625d83e5df62ee4ab010a
5
+ SHA512:
6
+ metadata.gz: d4eb3bf019168c863b72ed5c3eb05567ec5233fcfe71ca570f561fd08ad0da569f1bac69317f2c227c373144a05468e2efca751db90846e729fd47deb9741e03
7
+ data.tar.gz: 166c7fccd1d8085dba1cdf4c6eb49685d2ce20bdbb606fd58082dcd4e0e59c8dbd91f88474bd111ab58d431af0e062c0a11cfa128ce085c6def53ead5651b505
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ .bundle
3
+ .config
4
+ .ruby-gemset
5
+ .ruby-version
6
+ .rvmrc
7
+ .rspec
8
+ .yardoc
9
+ Gemfile.lock
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Simon Repp
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # Titlekit [![Build Status](https://travis-ci.org/simonrepp/titlekit.png)](https://travis-ci.org/simonrepp/titlekit)
2
+
3
+ Featureful Ruby 2 library for SRT / ASS / SSA subtitles
4
+
5
+ *Titlekit supports SRT, ASS and SSA, file format conversion, transcoding, automatic encoding detection, creation of simultaneous/multi-language subtitles, and timecode corrections with simple, progressive and framerate-based approaches. All of this is packed into a natural, dead-simple (and also irb-friendly) API.*
6
+
7
+ ## Installation
8
+
9
+ **Patch level 2.0.0-p195 is mandatory because it contains necessary bugfixes for the new keyword arguments.**
10
+
11
+ Add the `titlekit` gem to your gemfile or install it yourself:
12
+
13
+ $ gem install titlekit
14
+
15
+ ### Optional installation recommendation
16
+
17
+ Titlekit uses [rchardet19](https://github.com/oleander/rchardet) to detect unknown encodings; There is another library for this task called [charlock_holmes](https://github.com/brianmario/charlock_holmes), which offers more robust detection algorithms, but is not included by default because it relies on external C libraries that can make its installation anywhere from semi-easy to impossible. If you want Titlekit to use *charlock_holmes*, install it yourself, and Titlekit will automatically use it over *rchardet19*!
18
+
19
+ ## Documentation
20
+
21
+ ### Basic example
22
+
23
+ A small hello world of Titlekit: **Converting from .srt to .ssa format**
24
+
25
+ ```ruby
26
+ job = Titlekit::Job.new # (1) Initialize
27
+ job.have { file('existing.srt') } # (2) Specify what you have
28
+ job.want { file('converted.ssa') } # (3) Specify what you want
29
+ job.run # (4) Make it happen
30
+ ```
31
+ ### Checking success
32
+
33
+ The return value from `#run` will tell you if the job was a success. If it was not,
34
+ you can access `#report` to get messages related to the direct failure cause and also on
35
+ anything suspicious that might have happened before (e.g. Low confidence when detecting an
36
+ unknown encoding)
37
+
38
+ ```ruby
39
+ if job.run
40
+ # hooray
41
+ else
42
+ puts job.report.join("\n")
43
+ end
44
+ ```
45
+
46
+ ### All features by example
47
+
48
+ In all following examples I will omit `(1)` and `(4)` from the basic example, because they stay the same.
49
+ All the functionalities from all the following examples can be combined in any way you want.
50
+
51
+ #### Transcoding
52
+
53
+ ```ruby
54
+ job.have do
55
+ file('input.srt')
56
+ encoding('ISO-8859-1')
57
+ end
58
+
59
+ job.want do
60
+ file('output.srt')
61
+ encoding('UTF-8')
62
+ end
63
+ ```
64
+
65
+ #### Converting
66
+
67
+ ```ruby
68
+ job.have { file('input.ass') }
69
+ job.want { file('output.srt') }
70
+ ```
71
+
72
+ #### Simple timeshifting
73
+
74
+ ```ruby
75
+ job.have do
76
+ file('input.srt')
77
+ reference('first sentence spoken', subtitle: 0)
78
+ end
79
+
80
+ job.want do
81
+ file('output.srt')
82
+ reference('first sentence spoken', srt_timecode: '00:00:54,200')
83
+ end
84
+ ```
85
+
86
+ #### Progressive timeshifting
87
+
88
+ ```ruby
89
+ job.have do
90
+ file('input.srt')
91
+ reference('first subtitle', subtitle: 0)
92
+ reference('last subtitle', subtitle: 475)
93
+ end
94
+
95
+ job.want do
96
+ file('output.srt')
97
+ reference('first subtitle', minutes: 3.76)
98
+ reference('last subtitle', hours: 1.8912)
99
+ end
100
+ ```
101
+
102
+ #### Framerate-based timeshifting
103
+
104
+ ```ruby
105
+ job.have do
106
+ file('input.srt')
107
+ fps(25)
108
+ end
109
+
110
+ job.want do
111
+ file('output.srt')
112
+ fps(23.976)
113
+ end
114
+ ```
115
+
116
+ #### Mixed mode timeshifting
117
+
118
+ ```ruby
119
+ job.have do
120
+ file('input.srt')
121
+ fps(25)
122
+ reference(:first_sub, subtitle: 0)
123
+ end
124
+
125
+ job.want do
126
+ file('output.srt')
127
+ fps(23.976)
128
+ reference(:first_sub, minute: 13.49)
129
+ end
130
+ ```
131
+
132
+ #### Merging
133
+
134
+ Subtitles that don't overlap are automatically merged and treated as one track.
135
+
136
+ ```ruby
137
+ job.have do
138
+ file('subs_chapter1.srt')
139
+ end
140
+
141
+ job.have do
142
+ file('subs_chapter2.srt')
143
+ end
144
+
145
+ job.want do
146
+ file('subs_both_chapters_combined.srt')
147
+ end
148
+ ```
149
+
150
+ #### Merging (with time correction)
151
+
152
+ If each of your individual subtitle files contains timecodes relative to its own starting point,
153
+ you have to supply a reference so misaligned subtitles can be automatically shifted. When you fail
154
+ to do this, your subtitles overlap and thus Titlekit assumes that you want simultaneous subtitles (which are explained in the next paragraph below this one).
155
+
156
+ ```ruby
157
+ job.have do
158
+ file('subs_cd1.srt')
159
+ end
160
+
161
+ job.have do
162
+ file('subs_cd2.srt')
163
+ reference(:cd2_subtitles_starting_at, minutes: 0)
164
+ end
165
+
166
+ job.want do
167
+ reference(:cd2_subtitles_starting_at, srt_timecode: '00:01:24,000')
168
+ file('subs_both_cds_combined.srt')
169
+ end
170
+ ```
171
+
172
+ #### Simultaneous/multi-lanugage subtitles
173
+
174
+ Subtitles that overlap are automatically treated as simultaneous/multi-lanugage subtitles.
175
+ Titlekit then positions and formats them in the most sensible way it sees fit.
176
+
177
+ ```ruby
178
+ job.have { file('enlish.srt') }
179
+ job.have { file('dutch.srt') }
180
+ job.want { file('dual-language.srt') }
181
+ ```
182
+
183
+ Any target format is possible, Titlekit will automatically make the best use of the formatting
184
+ features your target format provides. Pick a sophisticated subtitle format, and your dual
185
+ subtitles will automatically be prettier and more readable!
186
+
187
+ ```ruby
188
+ job.have { file('enlish.srt') }
189
+ job.have { file('dutch.srt') }
190
+ job.want { file('dual-language-prettier.ass') }
191
+ ```
192
+
193
+ You can also go crazy if you want, Titlekit can handle it.
194
+
195
+ ```ruby
196
+ job.have { file('enlish.srt') }
197
+ job.have { file('dutch.srt') }
198
+ job.have { file('spanish.srt') }
199
+ job.have { file('german.srt') }
200
+ job.have { file('italian.srt') }
201
+ job.have { file('french.srt') }
202
+ job.have { file('portuguese.srt') }
203
+ job.have { file('russian.srt') }
204
+ job.want { file('messy-but-supported.ssa') }
205
+ ```
206
+
207
+ #### Mixed mode Merging (implicit)
208
+
209
+ If you really need the absurdly exotic case of merging multi-part subtitles into multiple simultaneous tracks, you just need to make sure you enter them in the correct order, which is: Lanuage1/Part1 -> Language1/Part2 -> Language2/Part1 -> Language2/Part2
210
+
211
+ ```ruby
212
+ job.have { file('subs_english_chapter1.srt')
213
+ job.have { file('subs_english_chapter2.srt')
214
+ job.have { file('subs_french_chapter1.srt')
215
+ job.have { file('subs_french_chapter2.srt')
216
+
217
+ job.want do
218
+ file('subs_multi_part_multi_track.srt')
219
+ end
220
+ ```
221
+
222
+ #### Mixed mode Merging (explicit)
223
+
224
+ If you supply explicit track identifiers by which to material should be grouped into tracks,
225
+ you can also forget all about the otherwise required order and just go wild:
226
+
227
+ ```ruby
228
+
229
+ job.have do
230
+ file('subs_french_chapter2.srt')
231
+ track('le-french-track')
232
+ end
233
+
234
+ job.have do
235
+ file('subs_english_chapter1.srt')
236
+ track('the-english-one')
237
+ end
238
+
239
+ job.have do
240
+ file('subs_french_chapter1.srt')
241
+ track('le-french-track')
242
+ end
243
+
244
+ job.have do
245
+ file('subs_english_chapter2.srt')
246
+ track('the-english-one')
247
+ end
248
+
249
+ job.want do
250
+ file('subs_multi_part_multi_track.srt')
251
+ end
252
+ ```
253
+
254
+ #### Multiple targets
255
+
256
+ ```ruby
257
+ job.have { file('input.srt') }
258
+ job.want { file('output.ass') }
259
+ job.want { file('output.ssa') }
260
+ ```
261
+
262
+ #### Templates
263
+
264
+ ```ruby
265
+ job.have do
266
+ file('input.srt')
267
+ encoding('Shift_JIS')
268
+ reference(:some_subtitle, subtitle: 23)
269
+ end
270
+
271
+ templ = job.want do
272
+ file('output.srt')
273
+ encoding('UTF-8')
274
+ reference(:some_subtitle, hours: 0.16)
275
+ end
276
+
277
+ job.want(template: templ) { file('output.ass') }
278
+ job.want(template: templ) { file('output.ssa') }
279
+ ```
280
+
281
+ #### Explicitly control encoding detection
282
+
283
+ ```ruby
284
+ job.have do
285
+ file('input.srt')
286
+ encoding(:detect) # Detect the encoding with charlock_holmes if installed, otherwise rchardet19
287
+ # You don't need to supply this line though, it's the default behavior!
288
+ end
289
+
290
+ job.have do
291
+ file('input.srt')
292
+ encoding(:rchardet19) # Explicitly use rchardet19
293
+ end
294
+
295
+ job.have do
296
+ file('input.srt')
297
+ encoding(:charlock_holmes) # Explicitly use charlock_holmes
298
+ end
299
+ ```
300
+
301
+ #### Syntax Variants
302
+
303
+ `#have` and `#want` offer three different syntax variants, which are functionally identical:
304
+
305
+ ```ruby
306
+ job.have do
307
+ file('input.srt')
308
+ encoding('ISO-8859-1')
309
+ end
310
+
311
+ # is identical to
312
+
313
+ job.have do |have|
314
+ have.file('input.srt')
315
+ have.encoding('ISO-8859-1')
316
+ end
317
+
318
+ # is identical to
319
+
320
+ have = job.have
321
+ have.file('input.srt')
322
+ have.encoding('ISO-8859-1')
323
+ ```
324
+
325
+ ## API Reference
326
+
327
+ http://www.rubydoc.info/gems/titlekit/frames (or generate it yourself with YARD)
328
+
329
+ ## Contributing
330
+
331
+ 1. Fork it
332
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
333
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
334
+ 4. Push to the branch (`git push origin my-new-feature`)
335
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
@@ -0,0 +1,90 @@
1
+ module Titlekit
2
+
3
+ # Specifies existing input for a job.
4
+ class Have < Specification
5
+
6
+ def initialize
7
+ super
8
+
9
+ @encoding = :detect
10
+ end
11
+
12
+ # @param [String, Symbol] A string specifying the encoding if it is known,
13
+ # (e.g. 'UTF-8', 'ISO-8859-1'), :detect in case you don't know, and
14
+ # :rchardet19 or :charlock_holmes if you have installed an additional
15
+ # detection library and want to specifically use one or the other.
16
+ #
17
+ # @return If you omit the argument, it returns the already specified encoding
18
+ def encoding(*args)
19
+ if args.empty?
20
+ return @encoding
21
+ else
22
+ @encoding = args[0]
23
+ return self
24
+ end
25
+ end
26
+
27
+ # Places a named reference (in the form of a string or a symbol) on
28
+ # either a +subtitle+ index or a timecode specified by either
29
+ # +hours+, +minutes+, +seconds+ or +milliseconds+.
30
+ #
31
+ # Its typical use-case is to reference a specific subtitle you can
32
+ # recognize in both the movie and your subtitle file, where usually
33
+ # for the subtitle file (represented by {Have}) you will reference
34
+ # the subtitle index and for the movie (represented by {Want}) you
35
+ # will reference the timecode that is displayed when the line occurs
36
+ # in the movie.
37
+ #
38
+ # @example Referencing a subtitle index (ZERO-INDEXED! First subtitle is 0)
39
+ # have.reference('Earl grey, hot', subtitle: 645)
40
+ #
41
+ # @example Referencing a timecode by seconds
42
+ # have.reference('In a galaxy ...', seconds: 14.2)
43
+ #
44
+ # @example Referencing a timecode by an SRT-style timecode
45
+ # have.reference('In a galaxy ...', srt_timecode: '00:00:14,200')
46
+ #
47
+ # @example Referencing a timecode by an ASS-style timecode
48
+ # have.reference('In a galaxy ...', ass_timecode: '0:00:14,20')
49
+ #
50
+ # @example Referencing a timecode by an SSA-style timecode
51
+ # have.reference('In a galaxy ...', ssa_timecode: '0:00:14,20')
52
+ #
53
+ # @example Symbols can be used as references as well!
54
+ # have.reference(:narrator_begins, minutes: 7.9)
55
+ #
56
+ # @param name [String, Symbol] The name of the reference
57
+ # @param subtitle [Integer] Heads up: Numbering starts at 1!
58
+ # @param hours [Float]
59
+ # @param minutes [Float]
60
+ # @param seconds [Float]
61
+ # @param milliseconds [Float]
62
+ def reference(name,
63
+ *args,
64
+ subtitle: nil,
65
+ hours: nil,
66
+ minutes: nil,
67
+ seconds: nil,
68
+ milliseconds: nil,
69
+ srt_timecode: nil,
70
+ ssa_timecode: nil,
71
+ ass_timecode: nil)
72
+
73
+ if subtitle
74
+ @references[name] = { subtitle: subtitle }
75
+ else
76
+ super(name,
77
+ hours: hours,
78
+ minutes: minutes,
79
+ seconds: seconds,
80
+ milliseconds: milliseconds,
81
+ srt_timecode: srt_timecode,
82
+ ssa_timecode: ssa_timecode,
83
+ ass_timecode: ass_timecode)
84
+ end
85
+
86
+ return self
87
+ end
88
+ end
89
+
90
+ end