titlekit 1.0.0

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.
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