m3uzi 0.1.4 → 0.1.6

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/lib/m3uzi.rb CHANGED
@@ -6,12 +6,13 @@ require 'm3uzi/version'
6
6
 
7
7
  class M3Uzi
8
8
 
9
- # Unsupported: KEY PROGRAM-DATE-TIME DISCONTINUITY
10
- VALID_TAGS = %w{TARGETDURATION MEDIA-SEQUENCE ALLOW-CACHE ENDLIST VERSION}
9
+ # Unsupported: PROGRAM-DATE-TIME DISCONTINUITY
10
+ VALID_TAGS = %w{TARGETDURATION MEDIA-SEQUENCE ALLOW-CACHE ENDLIST KEY}
11
11
 
12
12
  attr_accessor :files, :streams
13
13
  attr_accessor :tags, :comments
14
14
  attr_accessor :final_media_file
15
+ attr_accessor :version
15
16
 
16
17
  def initialize
17
18
  @files = []
@@ -19,6 +20,7 @@ class M3Uzi
19
20
  @tags = []
20
21
  @comments = []
21
22
  @final_media_file = true
23
+ @version = 1
22
24
  end
23
25
 
24
26
 
@@ -65,31 +67,38 @@ class M3Uzi
65
67
  m3u
66
68
  end
67
69
 
68
- def write(path)
69
- f = ::File.open(path, "w")
70
- f << "#EXTM3U\n"
70
+ def write_to_io(io_stream)
71
+ check_version_restrictions
72
+ io_stream << "#EXTM3U\n"
73
+ io_stream << "#EXT-X-VERSION:#{@version.to_i}" if @version > 1
71
74
  comments.each do |comment|
72
- f << "##{comment}\n"
75
+ io_stream << "##{comment}\n"
73
76
  end
74
77
  tags.each do |tag|
75
78
  next if %w{M3U ENDLIST}.include?(tag.name.to_s.upcase)
76
79
  if VALID_TAGS.include?(tag.name.to_s.upcase)
77
- f << "#EXT-X-#{tag.name.to_s.upcase}"
80
+ io_stream << "#EXT-X-#{tag.name.to_s.upcase}"
78
81
  else
79
- f << "##{tag.name.to_s.upcase}"
82
+ io_stream << "##{tag.name.to_s.upcase}"
80
83
  end
81
- tag.value && f << ":#{tag.value}"
82
- f << "\n"
84
+ tag.value && io_stream << ":#{tag.value}"
85
+ io_stream << "\n"
83
86
  end
84
87
  files.each do |file|
85
- f << "#EXTINF:#{file.attribute_string}"
86
- f << "\n#{file.path}\n"
88
+ io_stream << "#EXTINF:#{file.attribute_string}"
89
+ io_stream << "\n#{file.path}\n"
87
90
  end
88
91
  streams.each do |stream|
89
- f << "#EXT-X-STREAM-INF:#{stream.attribute_string}"
90
- f << "\n#{stream.path}\n"
92
+ io_stream << "#EXT-X-STREAM-INF:#{stream.attribute_string}"
93
+ io_stream << "\n#{stream.path}\n"
91
94
  end
92
- f << "#EXT-X-ENDLIST\n" if files.length > 0 && final_media_file
95
+ io_stream << "#EXT-X-ENDLIST\n" if files.length > 0 && final_media_file
96
+ end
97
+
98
+ def write(path)
99
+ check_version_restrictions
100
+ f = ::File.open(path, "w")
101
+ write_to_io(f)
93
102
  f.close()
94
103
  end
95
104
 
@@ -105,7 +114,7 @@ class M3Uzi
105
114
  end
106
115
 
107
116
  def filenames
108
- files.map{|file| file.path }
117
+ files.map { |file| file.path }
109
118
  end
110
119
 
111
120
 
@@ -120,7 +129,7 @@ class M3Uzi
120
129
  end
121
130
 
122
131
  def stream_names
123
- streams.map{|stream| stream.path }
132
+ streams.map { |stream| stream.path }
124
133
  end
125
134
 
126
135
 
@@ -136,7 +145,7 @@ class M3Uzi
136
145
 
137
146
  def [](key)
138
147
  tag_name = key.to_s.upcase.gsub("_", "-")
139
- obj = tags.detect{|tag| tag.name == tag_name }
148
+ obj = tags.detect { |tag| tag.name == tag_name }
140
149
  obj && obj.value
141
150
  end
142
151
 
@@ -160,6 +169,33 @@ class M3Uzi
160
169
  add_comment(comment)
161
170
  end
162
171
 
172
+ def check_version_restrictions
173
+ @version = 1
174
+
175
+ # Version 2 Features
176
+ if @tags.detect { |tag| tag.name == 'KEY' && tag.value.to_s =~ /,IV=/ }
177
+ @version = 2 if @version < 2
178
+ end
179
+
180
+ # Version 3 Features
181
+ if @files.detect { |file| file.duration.kind_of?(Float) }
182
+ @version = 3 if @version < 3
183
+ end
184
+
185
+ # Version 4 Features
186
+ if @files.detect { |file| file.byterange }
187
+ @version = 4 if @version < 4
188
+ end
189
+ if @tags.detect { |tag| ['MEDIA','I-FRAMES-ONLY'].include?(tag.name) }
190
+ @version = 4 if @version < 4
191
+ end
192
+
193
+ # NOTES
194
+ # EXT-X-I-FRAME-STREAM-INF is supposed to be ignored by older clients.
195
+ # AUDIO/VIDEO attributes of X-STREAM-INF are used in conjunction with MEDIA, so it should trigger v4.
196
+
197
+ @version
198
+ end
163
199
 
164
200
  protected
165
201
 
data/lib/m3uzi/file.rb CHANGED
@@ -1,10 +1,14 @@
1
1
  class M3Uzi
2
2
  class File
3
3
 
4
- attr_accessor :path, :duration, :description
4
+ attr_accessor :path, :duration, :description, :byterange
5
5
 
6
6
  def attribute_string
7
- "#{duration},#{description}"
7
+ if duration.kind_of?(Float)
8
+ "#{sprintf('%0.3f',duration)},#{description}"
9
+ else
10
+ "#{duration},#{description}"
11
+ end
8
12
  end
9
13
 
10
14
  end
data/lib/m3uzi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class M3Uzi
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.6'
3
3
  end
@@ -0,0 +1,78 @@
1
+ $: << File.join(File.dirname(__FILE__),'../lib')
2
+ require 'm3uzi'
3
+ require 'test/unit'
4
+ require 'rubygems'
5
+ require 'shoulda'
6
+
7
+ class M3UziTest < Test::Unit::TestCase
8
+
9
+ context "basic checks" do
10
+ should "instantiate an M3Uzi object" do
11
+ m3u = M3Uzi.new
12
+ assert_equal M3Uzi, m3u.class
13
+ end
14
+
15
+ should "read in an index file" do
16
+ m3u = M3Uzi.read(File.join(File.dirname(__FILE__), "fixtures/index.m3u8"))
17
+ assert_equal M3Uzi, m3u.class
18
+ end
19
+ end
20
+
21
+ context "with protocol versions" do
22
+ should "set version 2 for encryption IV" do
23
+ m3u = M3Uzi.new
24
+ m3u['KEY'] = "0x1234567890abcdef1234567890abcdef"
25
+ assert_equal 1, m3u.check_version_restrictions
26
+ m3u['KEY'] = "0x1234567890abcdef1234567890abcdef,IV=0x1234567890abcdef1234567890abcdef"
27
+ assert_equal 2, m3u.check_version_restrictions
28
+
29
+ output_stream = StringIO.new
30
+ m3u.write_to_io(output_stream)
31
+ assert output_stream.string =~ /,IV=/
32
+ end
33
+
34
+ should "set version 3 for floating point durations" do
35
+ m3u = M3Uzi.new
36
+ m3u.add_file do |f|
37
+ f.path = "stuff.ts"
38
+ f.duration = 10
39
+ end
40
+ assert_equal 1, m3u.check_version_restrictions
41
+
42
+ output_stream = StringIO.new
43
+ m3u.write_to_io(output_stream)
44
+ assert output_stream.string =~ /:10,/
45
+ assert output_stream.string !~ /:10\./
46
+
47
+ m3u = M3Uzi.new
48
+ m3u.add_file do |f|
49
+ f.path = "stuff.ts"
50
+ f.duration = 10.0
51
+ end
52
+ assert_equal 3, m3u.check_version_restrictions
53
+
54
+ output_stream = StringIO.new
55
+ m3u.write_to_io(output_stream)
56
+ assert output_stream.string =~ /:10\.000,/
57
+ assert output_stream.string !~ /:10,/
58
+ end
59
+
60
+ should "set version 4 for advanced features" do
61
+ m3u = M3Uzi.new
62
+ m3u.add_file do |f|
63
+ f.path = "stuff.ts"
64
+ f.duration = 10
65
+ end
66
+ assert_equal 1, m3u.check_version_restrictions
67
+
68
+ m3u = M3Uzi.new
69
+ m3u.add_file do |f|
70
+ f.path = "stuff.ts"
71
+ f.duration = 10.0
72
+ f.byterange = "1234@0"
73
+ end
74
+ assert_equal 4, m3u.check_version_restrictions
75
+ end
76
+ end
77
+
78
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: m3uzi
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 1
9
- - 4
10
- version: 0.1.4
8
+ - 6
9
+ version: 0.1.6
11
10
  platform: ruby
12
11
  authors:
13
12
  - Brandon Arbini
@@ -16,7 +15,7 @@ autorequire:
16
15
  bindir: bin
17
16
  cert_chain: []
18
17
 
19
- date: 2011-01-09 00:00:00 -06:00
18
+ date: 2011-10-10 00:00:00 -05:00
20
19
  default_executable:
21
20
  dependencies: []
22
21
 
@@ -38,7 +37,7 @@ files:
38
37
  - lib/m3uzi.rb
39
38
  - test/fixtures/index.m3u8
40
39
  - test/fixtures/stream.m3u8
41
- - test/m3uzzi_test.rb
40
+ - test/m3uzi_test.rb
42
41
  - LICENSE
43
42
  - Rakefile
44
43
  - README.md
@@ -52,27 +51,23 @@ rdoc_options: []
52
51
  require_paths:
53
52
  - lib
54
53
  required_ruby_version: !ruby/object:Gem::Requirement
55
- none: false
56
54
  requirements:
57
55
  - - ">="
58
56
  - !ruby/object:Gem::Version
59
- hash: 3
60
57
  segments:
61
58
  - 0
62
59
  version: "0"
63
60
  required_rubygems_version: !ruby/object:Gem::Requirement
64
- none: false
65
61
  requirements:
66
62
  - - ">="
67
63
  - !ruby/object:Gem::Version
68
- hash: 3
69
64
  segments:
70
65
  - 0
71
66
  version: "0"
72
67
  requirements: []
73
68
 
74
69
  rubyforge_project:
75
- rubygems_version: 1.3.7
70
+ rubygems_version: 1.3.6
76
71
  signing_key:
77
72
  specification_version: 3
78
73
  summary: Read and write M3U files with (relative) ease.
data/test/m3uzzi_test.rb DELETED
@@ -1,18 +0,0 @@
1
- require 'rubygems'
2
- require 'm3uzzi'
3
- require 'test/unit'
4
- require 'shoulda'
5
-
6
- class M3UziTest < Test::Unit::TestCase
7
-
8
- should "instantiate an M3Uzi object" do
9
- m3u = M3Uzi.new
10
- assert_equal M3Uzi, m3u.class
11
- end
12
-
13
- should "read in an index file" do
14
- m3u = M3Uzi.read_file("#{Rails.root}/test/fixtures/index.m3u8")
15
- assert_equal M3Uzi, m3u.class
16
- end
17
-
18
- end