nofxx-subtitle_it 0.6.1

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 (50) hide show
  1. data/.autotest +19 -0
  2. data/History.txt +30 -0
  3. data/License.txt +20 -0
  4. data/Manifest.txt +49 -0
  5. data/README.markdown +41 -0
  6. data/README.txt +84 -0
  7. data/Rakefile +4 -0
  8. data/bin/subtitle_it +115 -0
  9. data/config/hoe.rb +73 -0
  10. data/config/requirements.rb +15 -0
  11. data/lib/subtitle_it.rb +46 -0
  12. data/lib/subtitle_it/formats/ass.rb +14 -0
  13. data/lib/subtitle_it/formats/rsb.rb +33 -0
  14. data/lib/subtitle_it/formats/srt.rb +34 -0
  15. data/lib/subtitle_it/formats/sub.rb +31 -0
  16. data/lib/subtitle_it/formats/xml.rb +64 -0
  17. data/lib/subtitle_it/formats/yml.rb +20 -0
  18. data/lib/subtitle_it/subline.rb +25 -0
  19. data/lib/subtitle_it/subtime.rb +58 -0
  20. data/lib/subtitle_it/subtitle.rb +32 -0
  21. data/lib/subtitle_it/version.rb +9 -0
  22. data/script/console +10 -0
  23. data/script/destroy +14 -0
  24. data/script/generate +14 -0
  25. data/script/txt2html +82 -0
  26. data/setup.rb +1585 -0
  27. data/spec/fixtures/godfather.srt +2487 -0
  28. data/spec/fixtures/huge.ass +22 -0
  29. data/spec/fixtures/movie.xml +28 -0
  30. data/spec/fixtures/movie.yml +163 -0
  31. data/spec/fixtures/pseudo.rsb +6 -0
  32. data/spec/fixtures/pulpfiction.sub +2025 -0
  33. data/spec/fixtures/sincity.yml +12 -0
  34. data/spec/spec.opts +1 -0
  35. data/spec/spec_helper.rb +33 -0
  36. data/spec/subtitle_it/formats/ass_spec.rb +5 -0
  37. data/spec/subtitle_it/formats/rsb_spec.rb +42 -0
  38. data/spec/subtitle_it/formats/srt_spec.rb +42 -0
  39. data/spec/subtitle_it/formats/sub_spec.rb +46 -0
  40. data/spec/subtitle_it/formats/xml_spec.rb +46 -0
  41. data/spec/subtitle_it/formats/yml_spec.rb +20 -0
  42. data/spec/subtitle_it/subline_spec.rb +30 -0
  43. data/spec/subtitle_it/subtime_spec.rb +76 -0
  44. data/spec/subtitle_it/subtitle_spec.rb +1 -0
  45. data/spec/subtitle_it_spec.rb +11 -0
  46. data/subtitle_it.gemspec +41 -0
  47. data/tasks/deployment.rake +34 -0
  48. data/tasks/environment.rake +7 -0
  49. data/tasks/rspec.rake +21 -0
  50. metadata +128 -0
@@ -0,0 +1,46 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+ require 'rubygems'
4
+ require 'subtitle_it/version'
5
+ require 'subtitle_it/subtime'
6
+ require 'subtitle_it/subline'
7
+ require 'subtitle_it/subtitle'
8
+
9
+ module SubtitleIt
10
+ end
11
+
12
+ class Numeric
13
+ def reduce
14
+ self / ( 10 ** Math::log10(self).to_i)
15
+ end
16
+ end
17
+
18
+ class String
19
+ def to_msec
20
+ # convert string in time format to milli sec format
21
+ # "12:23:34,567" => "12*60*60*1000 + 23*60*1000 + 34 *1000 + 567"
22
+ time_list = self.split(/:/)
23
+ sec, msec = time_list.pop().split(/,|\./)
24
+ time_list.push(sec)
25
+ p time_list if $DEBUG
26
+ msecs = msec.to_i
27
+ time_list.reverse!
28
+ time_list.each_with_index { |x,i| msecs += x.to_i * 60**i * 1000 }
29
+ p msecs if $DEBUG
30
+ msecs#.to_s
31
+ end
32
+ end
33
+
34
+ class Fixnum
35
+ def to_time()
36
+ # convert millisec to standard time format
37
+ # 3600 * 1000 = ,000
38
+ time = self
39
+ msec = "%.3d" % (time % 1000)
40
+ time /= 1000
41
+ time_list = []
42
+ 3.times { time_list.unshift( "%.2d"% (time%60) ) ; time /= 60 }
43
+ p time_list if $DEBUG
44
+ [ time_list.join(':'),msec ].join(',')
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ # SubtitleIt
2
+ # ASS - http://en.wikipedia.org/wiki/SubStation_Alpha
3
+ #
4
+ module SubtitleIt
5
+ module Formats
6
+ def parse_ass
7
+
8
+ end
9
+
10
+ #not mine!
11
+ def to_ass
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ # SubtitleIt
2
+ # RSB - Ruby Subtitle
3
+ #
4
+ # 00:32 => 00:33 == Nice police work! | Thank you!
5
+ # 00:53 => N == Howdy ho!
6
+ # MM:SS => N == TEXT | NEWLINE
7
+ #
8
+ # Where N is the seconds to last.
9
+ #
10
+ module SubtitleIt
11
+ module Formats
12
+ def parse_rsb
13
+ inn = @raw.to_a
14
+ @title = inn.delete_at(0).split(':')[1]
15
+ @authors = inn.delete_at(0).split(':')[1]
16
+ @version = inn.delete_at(0).split(':')[1]
17
+ inn.inject([]) do |final,line|
18
+ text_on,text_off = line.split('=>').map { |t| t.strip }
19
+ text = line.split('==')[1].strip
20
+ final << Subline.new(text_on, text_off, text)
21
+ end
22
+ end
23
+
24
+ def to_rsb
25
+ out = "- title: #{@title}\n- authors: #{@authors}\n- version: #{@version}\n"
26
+ out << @lines.inject([]) do |i,l|
27
+ i << "%s => %s == %s" % [l.text_on.to_s, l.text_off.to_s, l.text]
28
+ end.join("\n")
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,34 @@
1
+ # SubtitleIt
2
+ # SRT format
3
+ #
4
+ # N
5
+ # 00:55:21,600 --> 00:55:27,197
6
+ # lt's not even 20 years. You've sold the
7
+ # casinos and made fortunes for all of us.
8
+ #
9
+ # Where N is the sub index number
10
+ #
11
+ module SubtitleIt
12
+ module Formats
13
+ def parse_srt
14
+ @raw.split(/\n\n/).inject([]) do |final,line|
15
+ line = line.split(/\n/)
16
+ line.delete_at(0)
17
+ text_on,text_off = line[0].split('-->').map { |t| t.strip }
18
+ line.delete_at(0)
19
+ text = line.join("|")
20
+ final << Subline.new(text_on, text_off, text)
21
+ end
22
+ end
23
+
24
+ def to_srt
25
+ out = []
26
+ @lines.each_with_index do |l,i|
27
+ out << "#{i}"
28
+ out << "%s --> %s" % [l.text_on.to_s, l.text_off.to_s]
29
+ out << l.text.gsub("|","\n")
30
+ end
31
+ out.join("\n")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ # SubtitleIt
2
+ # MicroDVD - Subrip format
3
+ #
4
+ # {1025}{1115}You always say that.|The same thing every time.
5
+ # {1118}{1177}"l'm throug h, never again,|too dangerous."
6
+ #
7
+ # Where N is ms / framerate / 1000 (ms -> s)
8
+ #
9
+ # parts of the code from 'simplesubtitler' from Marcin (tiraeth) Chwedziak
10
+ #
11
+ module SubtitleIt
12
+ module Formats
13
+ def parse_sub
14
+ @raw.to_a.inject([]) do |i,l|
15
+ line_data = l.scan(/^\{([0-9]{1,})\}\{([0-9]{1,})\}(.+)$/)
16
+ line_data = line_data.at 0
17
+ text_on, text_off, text = line_data
18
+ text_on, text_off = [text_on.to_i, text_off.to_i].map { |t| (t.to_i/@fps*1000).to_i }
19
+ i << Subline.new(text_on, text_off, text.chomp)
20
+ end
21
+ end
22
+
23
+ def to_sub
24
+ @lines.inject([]) do |i,l|
25
+ start = l.text_on.to_i / @fps / 1000
26
+ stop = l.text_off.to_i / @fps / 1000
27
+ i << "{%d}{%d}%s" % [start, stop, l.text]
28
+ end.join("\r\n")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,64 @@
1
+ # SubtitleIt
2
+ # XML TT Timed Text
3
+ # http://www.w3.org/TR/2006/CR-ttaf1-dfxp-20061116/
4
+ # http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000604.html
5
+ #
6
+ # <?xml version="1.0" encoding="UTF-8"?>
7
+ # <tt xml:lang="en" xmlns="http://www.w3.org/2006/04/ttaf1" xmlns:tts="http://www.w3.org/2006/04/ttaf1#styling">
8
+ # <head>
9
+ # <styling>
10
+ # <style id="1" tts:textAlign="right"/>
11
+ # <style id="2" tts:color="transparent"/>
12
+ # </styling>
13
+ # </head>
14
+ # <body>
15
+ # <div xml:lang="en">
16
+ # <p begin="00:00:00.00" dur="00:00:03.07">I had just joined <span tts:fontFamily="monospaceSansSerif,proportionalSerif,TheOther"tts:fontSize="+2">Macromedia</span> in 1996,</p>
17
+ # <p begin="00:00:03.07" dur="00:00:03.35">and we were trying to figure out what to do about the internet.</p>
18
+ # <p begin="00:00:29.02" dur="00:00:01.30" style="1">as <span tts:color="#ccc333">easy</span> as drawing on paper.</p>
19
+ # </div>
20
+ # </body>
21
+ #</tt>
22
+ require 'hpricot'
23
+ module SubtitleIt
24
+ module Formats
25
+
26
+ def parse_xml
27
+ final = []
28
+ doc = Hpricot.XML(@raw)
29
+ # p (doc/'tt'/'p').first[:dur]#inspect
30
+ (doc/'tt'/'p').each do |line|
31
+ text_on = line[:begin]
32
+ text_off = line[:dur]
33
+ text = line.innerHTML
34
+ final << Subline.new(text_on,text_off,text)
35
+ end
36
+ final
37
+ end
38
+
39
+ def xml_lines
40
+ @lines.inject([]) do |i,l|
41
+ toff = l.text_off - l.text_on
42
+ i << "<p begin=\"#{l.text_on}\" dur=\"#{toff}\">#{l.text}</p>"
43
+ end
44
+ end
45
+
46
+ def to_xml
47
+ out = <<XML
48
+ <?xml version="1.0" encoding="UTF-8"?>
49
+ <tt xml:lang="en" xmlns="http://www.w3.org/2006/04/ttaf1" xmlns:tts="http://www.w3.org/2006/04/ttaf1#styling">
50
+ <head>
51
+ <styling>
52
+ #{@style}
53
+ </styling>
54
+ </head>
55
+ <body>
56
+ <div xml:lang="en">
57
+ #{xml_lines}
58
+ </div>
59
+ </body>
60
+ </tt>
61
+ XML
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,20 @@
1
+ # SubtitleIt
2
+ # YML Dump
3
+ #
4
+ require 'yaml'
5
+ module SubtitleIt
6
+ module Formats
7
+ def parse_yml
8
+ @yaml = YAML::load(@raw)
9
+ header = @yaml.delete('header')
10
+ @title = header['title']
11
+ @author = header['authors']
12
+ @version = header['version']
13
+ @yaml['lines'].map { |l| Subline.new(l[0], l[1], l[2]) }
14
+ end
15
+
16
+ def to_yml
17
+ YAML.dump(self)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ # SubtitleIt
2
+ # Holds a subtitle`s line.
3
+ module SubtitleIt
4
+ class Subline
5
+ attr_accessor :text_on, :text_off, :text
6
+ # text_on/off may be:
7
+ # HH:MM:SS,MMM
8
+ # MM:SS
9
+ # S
10
+ # text lines should be separated by |
11
+ def initialize(text_on, text_off, text)
12
+ @text_on, @text_off = filter(text_on, text_off)
13
+ # ugly FIXME: when pseudo uses time => 3
14
+ # need to add seconds from the first sub
15
+ @text_off += @text_on if @text_off < @text_on
16
+ @text = text
17
+ end
18
+
19
+ def filter(*args)
20
+ args.map do |arg|
21
+ Subtime.new(arg)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ # SubtitleIt
2
+ # Time class
3
+ module SubtitleIt
4
+ class Subtime
5
+ attr_accessor :hrs, :min, :sec, :ms
6
+
7
+ def initialize(sym)
8
+ @hrs = @min = @sec = @ms = 0
9
+ parse_subtime(sym)
10
+ end
11
+
12
+ def parse_subtime(sym)
13
+ if sym.kind_of?(Numeric)
14
+ @hrs = sym / 3600000
15
+ @min = sym / 60000 % 600
16
+ @sec = sym / 1000 % 60
17
+ @ms = sym % 1000
18
+ return
19
+ end
20
+ v = sym.split(/\.|\,/)
21
+ if ms = v[1]
22
+ @ms = (("0.%d" % ms.to_i).to_f * 1000).to_i
23
+ end
24
+ v = v[0].split(/:/).map { |s| s.to_i }
25
+ case v.size
26
+ when 1
27
+ @sec = v.first
28
+ when 2
29
+ @min, @sec = v
30
+ when 3
31
+ @hrs, @min, @sec = v
32
+ else
33
+ raise "Wrong time format"
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ "%02d:%02d:%02d.%s" % [@hrs, @min, @sec, ("%03d" % @ms) ]
39
+ end
40
+
41
+ def to_i
42
+ to_s.to_msec
43
+ end
44
+
45
+ def +(other)
46
+ Subtime.new(self.to_i + other.to_i)
47
+ end
48
+
49
+ def -(other)
50
+ Subtime.new(self.to_i - other.to_i)
51
+ end
52
+
53
+ def <=>(other)
54
+ self.to_i <=> other.to_i
55
+ end
56
+ include Comparable
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ require 'subtitle_it/formats/srt'
2
+ require 'subtitle_it/formats/sub'
3
+ require 'subtitle_it/formats/yml'
4
+ require 'subtitle_it/formats/rsb'
5
+ require 'subtitle_it/formats/xml'
6
+
7
+ module SubtitleIt
8
+ include Formats
9
+
10
+ class Subtitle
11
+ attr_reader :raw, :format, :lines, :style
12
+ EXTS = %w(srt sub smi txt ssa ass mpl xml yml rsb)
13
+
14
+ def initialize(dump, format, style=nil, fps=23.976)
15
+ raise unless format =~ /^srt$|^sub|yml|txt|rsb|xml|ass/
16
+ @raw = dump.kind_of?(String) ? dump : dump.read
17
+ @format = format
18
+ @style = style
19
+ @fps = fps
20
+ parse!
21
+ end
22
+
23
+ def parse!
24
+ self.lines = send :"parse_#{@format}"
25
+ end
26
+
27
+ private
28
+ def lines=(lines)
29
+ @lines = lines
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ module SubtitleIt
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 6
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/subtitle_it.rb'}"
9
+ puts "Loading subtitle_it gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ GEM_NAME = 'subtitle_it' # what ppl will type to install your gem
4
+ RUBYFORGE_PROJECT = 'subtitle_it'
5
+
6
+ require 'rubygems'
7
+ begin
8
+ require 'newgem'
9
+ require 'rubyforge'
10
+ rescue LoadError
11
+ puts "\n\nGenerating the website requires the newgem RubyGem"
12
+ puts "Install: gem install newgem\n\n"
13
+ exit(1)
14
+ end
15
+ require 'redcloth'
16
+ require 'syntax/convertors/html'
17
+ require 'erb'
18
+ require File.dirname(__FILE__) + "/../lib/#{GEM_NAME}/version.rb"
19
+
20
+ version = SubtitleIt::VERSION::STRING
21
+ download = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
22
+
23
+ def rubyforge_project_id
24
+ RubyForge.new.autoconfig["group_ids"][RUBYFORGE_PROJECT]
25
+ end
26
+
27
+ class Fixnum
28
+ def ordinal
29
+ # teens
30
+ return 'th' if (10..19).include?(self % 100)
31
+ # others
32
+ case self % 10
33
+ when 1: return 'st'
34
+ when 2: return 'nd'
35
+ when 3: return 'rd'
36
+ else return 'th'
37
+ end
38
+ end
39
+ end
40
+
41
+ class Time
42
+ def pretty
43
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
44
+ end
45
+ end
46
+
47
+ def convert_syntax(syntax, source)
48
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
49
+ end
50
+
51
+ if ARGV.length >= 1
52
+ src, template = ARGV
53
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
54
+ else
55
+ puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
56
+ exit!
57
+ end
58
+
59
+ template = ERB.new(File.open(template).read)
60
+
61
+ title = nil
62
+ body = nil
63
+ File.open(src) do |fsrc|
64
+ title_text = fsrc.readline
65
+ body_text_template = fsrc.read
66
+ body_text = ERB.new(body_text_template).result(binding)
67
+ syntax_items = []
68
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
69
+ ident = syntax_items.length
70
+ element, syntax, source = $1, $2, $3
71
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
72
+ "syntax-temp-#{ident}"
73
+ }
74
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
75
+ body = RedCloth.new(body_text).to_html
76
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
77
+ end
78
+ stat = File.stat(src)
79
+ created = stat.ctime
80
+ modified = stat.mtime
81
+
82
+ $stdout << template.result(binding)