mp3info 0.6.17

Sign up to get free protection for your applications and to get access to all the features.
data/mp3info.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'mp3info'
5
+ s.version = '0.6.17'
6
+ s.summary = %q{Read low-level informations and manipulate tags on mp3 files.}
7
+ s.homepage = "http://github.com/toy/#{s.name}"
8
+ s.authors = ['Guillaume Pierronnet', 'Ivan Kuchin']
9
+ s.license = 'ruby'
10
+
11
+ s.rubyforge_project = s.name
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = %w[lib]
17
+ end
data/test/fixtures.yml ADDED
@@ -0,0 +1,86 @@
1
+ empty_mp3: !binary |
2
+ eJz7/3tCCgP/BwaGTAYGBg4GBl4FBgZGIFoC5AKZJg0MDCw+jr6uxnqW5qEj
3
+ EAy43///npSyrx9/BA2Y4wYDGBQx9H80hnCD0Rga7GA0hkYBAQAA8NuaUA==
4
+ 2_2_tagged: !binary |
5
+ eNrtlrlOw0AQhn8QZ4E4CioK90jO2k58dGxs5xBxYiWbgiqKiAUWSmLZBFEi
6
+ XgDEM/AcPBN9imDHOBEIEB1H9tMW/8zO7szqb7ZqKcuI2T1gTAbWUR1chkMw
7
+ VwL2UQ69fiTQi67QGgVe2PdPkz1aAzZB/VBwutdgzWNgDVJO0uJjFFhNNNiJ
8
+ naRlQlQwswFsoeIHQmUY5JrdAGbDAXbgDc58Nhq4ZeqCAMyuA3tIUl4kXGki
9
+ EWVRUtPq86y63mg6EEiKlQnysZBmmdJ8y6ZToduKNK1R84oxE2m326xby3GL
10
+ eHe3LL0Kw5h3I6SgFaj6pr38nRE/EekcR9kcXtQxLavYqVoRJO1QpqZVMqgt
11
+ 23aeqKqu5PXkRfNhdEUr6LIGDofD4XD+KpPxfQ/bz4AfBxvxX0IAluL1GIex
12
+ zN8AKzXq2IpoaO0F5MffPhk/9J7uvjaovcj8Cocm3CHuEHeIO/RveQFv4P/e
13
+ vbr: !binary |
14
+ eNrt0F1k1XEYB/DnWHI0x0kiTTIzZqyRTS8jlV4kHSMdLdJFjuaQKYmMlCUm
15
+ siSbSBcZqbGNGYnpIimzRBKJLpKYmJFIU6f/uegyZ1f/yOfr4fc8PHwev8rS
16
+ jVLUSE+5rzd58hENuVg1PB91K7P1ufyatevWb9jY1NzS2ta+uWPLtq4dO/fs
17
+ P3Cw0H34yNFjx0+cLPWWT/edPXf+Qv/FS1euDl67PnTz1sjtO3fvjd5/MDY+
18
+ OTX96PHMk6fPXsy+fPX6zdt37z98/PR5/svC4tdv33/8TLyuQ7sL+zrat29t
19
+ rJuonrHpV0TnmebsrkJk5qp3DGTGn8f/nsrS6lLkFyPKyZCNyDVGZJIaTcak
20
+ 7bwcseLPRxX/lpoLxWLVaarhFGtlmc7elJxTKTmDKTkPU3LmUnIWUnIqQxwO
21
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
22
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
23
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
24
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
25
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
26
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
27
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
28
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
29
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
30
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
31
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
32
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
33
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
34
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
35
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
36
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
37
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
38
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
39
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
40
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
41
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
42
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
43
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
44
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
45
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
46
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
47
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
48
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
49
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
50
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
51
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
52
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
53
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
54
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
55
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
56
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
57
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
58
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
59
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
60
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
61
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
62
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
63
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
64
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
65
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
66
+ 4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4
67
+ HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6H
68
+ w+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+Fw
69
+ OBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO
70
+ h8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8Ph
71
+ cDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgc
72
+ DofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwOh8PhcDgcDofD
73
+ 4XA4HM4/dJYRDidN5zc6LQlL
74
+ audio_content_fixture: !binary |
75
+ SUQzAwAAAAABDFRBTEIAAAAnAAAB//5SAG8AZAByAGkAZwBvACAAeQAgAEcA
76
+ YQBiAHIAaQBlAGwAYQBUUkNLAAAABQAAAf/+MQBUSVQyAAAAEQAAAf/+VABh
77
+ AG0AYQBjAHUAbgBUUEUxAAAAJwAAAf/+UgBvAGQAcgBpAGcAbwAgAHkAIABH
78
+ AGEAYgByAGkAZQBsAGEA//uQZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
79
+ AAAAAAAAWGluZwAAAA8AAB7IAFw7mAADBQgKDQ8SFBcZHB4gIyUoKi4wMzU4
80
+ Oj1AQkVIS01QUlVYW11gYmRoam1vcnR3en1/gYSGiYuOkZSWmZueoKKmqKut
81
+ sLO2uLu9wMLFyMrNz9LU2Nrd3+Pl5+rs7/H19/r8//8AAABOTEFNRTMuOTAu
82
+ A74AAAAAAAAAADSAJAV8TQAAAABcO5gcQelNAAAAAAAAAAAAAAAAAAAAAAAA
83
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
84
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
85
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
86
+ AAAAAAAAAAAAAAAAAAAAAAA=
@@ -0,0 +1,572 @@
1
+ #!/usr/bin/env ruby1.9
2
+ # coding:utf-8
3
+
4
+ $:.unshift("lib/")
5
+
6
+ require "test/unit"
7
+ require "mp3info"
8
+ require "fileutils"
9
+ require "tempfile"
10
+ require "zlib"
11
+ require "yaml"
12
+
13
+ system("which id3v2 > /dev/null") || raise("id3v2 not found")
14
+
15
+ class Mp3InfoTest < Test::Unit::TestCase
16
+
17
+ TEMP_FILE = File.join(File.dirname(__FILE__), "test_mp3info.mp3")
18
+
19
+ DUMMY_TAG2 = {
20
+ "COMM" => "comments",
21
+ #"TCON" => "genre_s"
22
+ "TIT2" => "title",
23
+ "TPE1" => "artist",
24
+ "TALB" => "album",
25
+ "TYER" => "year",
26
+ "TRCK" => "tracknum"
27
+ }
28
+
29
+ DUMMY_TAG1 = {
30
+ "title" => "toto",
31
+ "artist" => "artist 123",
32
+ "album" => "ALBUMM",
33
+ "year" => 1934,
34
+ "tracknum" => 14,
35
+ "comments" => "comment me",
36
+ "genre" => 233
37
+ }
38
+
39
+ FIXTURES = YAML::load_file( File.join(File.dirname(__FILE__), "fixtures.yml") )
40
+
41
+ def setup
42
+ # Command to create a gzip'ed dummy MP3
43
+ # $ dd if=/dev/zero bs=1024 count=15 | \
44
+ # lame --quiet --preset cbr 128 -r -s 44.1 --bitwidth 16 - - | \
45
+ # ruby -rbase64 -rzlib -ryaml -e 'print(Zlib::Deflate.deflate($stdin.read)'
46
+ # vbr:
47
+ # $ dd if=/dev/zero of=#{tempfile.path} bs=1024 count=30000 |
48
+ # system("lame -h -v -b 112 -r -s 44.1 --bitwidth 16 - /tmp/vbr.mp3
49
+ @valid_mp3, @valid_mp3_2_2, @vbr_mp3 = %w{empty_mp3 2_2_tagged vbr}.collect do |fixture_key|
50
+ Zlib::Inflate.inflate(FIXTURES[fixture_key])
51
+ end
52
+
53
+ @tag = {
54
+ "title" => "title",
55
+ "artist" => "artist",
56
+ "album" => "album",
57
+ "year" => 1921,
58
+ "comments" => "comments",
59
+ "genre" => 0,
60
+ "genre_s" => "Blues",
61
+ "tracknum" => 36
62
+ }
63
+ File.open(TEMP_FILE, "w") { |f| f.write(@valid_mp3) }
64
+ end
65
+
66
+ def teardown
67
+ FileUtils.rm_f(TEMP_FILE)
68
+ end
69
+
70
+ def test_to_s
71
+ Mp3Info.open(TEMP_FILE) { |info| assert(info.to_s.is_a?(String)) }
72
+ end
73
+
74
+ def test_not_an_mp3
75
+ File.open(TEMP_FILE, "w") do |f|
76
+ str = "0"*1024*1024
77
+ f.write(str)
78
+ end
79
+ assert_raises(Mp3InfoError) do
80
+ mp3 = Mp3Info.new(TEMP_FILE)
81
+ end
82
+ end
83
+
84
+ def test_is_an_mp3
85
+ assert_nothing_raised do
86
+ Mp3Info.new(TEMP_FILE).close
87
+ end
88
+ end
89
+
90
+ def test_detected_info
91
+ Mp3Info.open(TEMP_FILE) do |mp3|
92
+ assert_mp3_info_are_ok(mp3)
93
+ end
94
+ end
95
+
96
+ def test_vbr_mp3_length
97
+ File.open(TEMP_FILE, "w") { |f| f.write(@vbr_mp3) }
98
+
99
+ Mp3Info.open(TEMP_FILE) do |info|
100
+ assert(info.vbr)
101
+ assert_in_delta(174.210612, info.length, 0.000001)
102
+ end
103
+ end
104
+
105
+ def test_removetag1
106
+ Mp3Info.open(TEMP_FILE) { |info| info.tag1 = @tag }
107
+ assert(Mp3Info.hastag1?(TEMP_FILE))
108
+ Mp3Info.removetag1(TEMP_FILE)
109
+ assert(! Mp3Info.hastag1?(TEMP_FILE))
110
+ end
111
+
112
+ def test_writetag1
113
+ Mp3Info.open(TEMP_FILE) { |info| info.tag1 = @tag }
114
+ Mp3Info.open(TEMP_FILE) { |info| assert_equal(info.tag1, @tag) }
115
+ end
116
+
117
+ def test_valid_tag1_1
118
+ tag = [ "title", "artist", "album", "1921", "comments", 36, 0].pack('A30A30A30A4a29CC')
119
+ valid_tag = {
120
+ "title" => "title",
121
+ "artist" => "artist",
122
+ "album" => "album",
123
+ "year" => 1921,
124
+ "comments" => "comments",
125
+ "genre" => "Blues",
126
+ #"version" => "1",
127
+ "tracknum" => 36
128
+ }
129
+ id3_test(tag, valid_tag)
130
+ end
131
+
132
+ def test_valid_tag1_0
133
+ tag = [ "title", "artist", "album", "1921", "comments", 0].pack('A30A30A30A4A30C')
134
+ valid_tag = {
135
+ "title" => "title",
136
+ "artist" => "artist",
137
+ "album" => "album",
138
+ "year" => 1921,
139
+ "comments" => "comments",
140
+ "genre" => "Blues",
141
+ #"version" => "0"
142
+ }
143
+ id3_test(tag, valid_tag)
144
+ end
145
+
146
+ def id3_test(tag_str, valid_tag)
147
+ tag = "TAG" + tag_str
148
+ File.open(TEMP_FILE, "w") do |f|
149
+ f.write(@valid_mp3)
150
+ f.write(tag)
151
+ end
152
+ assert(Mp3Info.hastag1?(TEMP_FILE))
153
+ #info = Mp3Info.new(TEMP_FILE)
154
+ #FIXME validate this test
155
+ #assert_equal(info.tag1, valid_tag)
156
+ end
157
+
158
+ def test_removetag2
159
+ w = write_tag2_to_temp_file({"TIT2" => "sdfqdsf"})
160
+
161
+ assert( Mp3Info.hastag2?(TEMP_FILE) )
162
+ Mp3Info.removetag2(TEMP_FILE)
163
+ assert( ! Mp3Info.hastag2?(TEMP_FILE) )
164
+ end
165
+
166
+ def test_hastags
167
+ Mp3Info.open(TEMP_FILE) do |info|
168
+ info.tag1 = @tag
169
+ end
170
+ assert(Mp3Info.hastag1?(TEMP_FILE))
171
+
172
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
173
+ assert(Mp3Info.hastag2?(TEMP_FILE))
174
+ end
175
+
176
+ def test_universal_tag
177
+ 2.times do
178
+ tag = {"title" => "title"}
179
+ Mp3Info.open(TEMP_FILE) do |mp3|
180
+ tag.each { |k,v| mp3.tag[k] = v }
181
+ end
182
+ w = Mp3Info.open(TEMP_FILE) { |m| m.tag }
183
+ assert_equal(tag, w)
184
+ end
185
+ end
186
+
187
+ def test_id3v2_universal_tag
188
+ tag = {}
189
+ %w{comments title artist album}.each { |k| tag[k] = k }
190
+ tag["tracknum"] = 34
191
+ Mp3Info.open(TEMP_FILE) do |mp3|
192
+ tag.each { |k,v| mp3.tag[k] = v }
193
+ end
194
+ w = Mp3Info.open(TEMP_FILE) { |m| m.tag }
195
+ w.delete("genre")
196
+ w.delete("genre_s")
197
+ assert_equal(tag, w)
198
+ # id3v2_prog_test(tag, w)
199
+ end
200
+
201
+ def test_id3v2_version
202
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
203
+ assert_equal( "2.#{ID3v2::WRITE_VERSION}.0", written_tag.version )
204
+ end
205
+
206
+ def test_id3v2_methods
207
+ tag = { "TIT2" => "tit2", "TPE1" => "tpe1" }
208
+ Mp3Info.open(TEMP_FILE) do |mp3|
209
+ tag.each do |k, v|
210
+ mp3.tag2.send("#{k}=".to_sym, v)
211
+ end
212
+ assert_equal(tag, mp3.tag2)
213
+ end
214
+ end
215
+
216
+ def test_id3v2_basic
217
+ w = write_tag2_to_temp_file(DUMMY_TAG2)
218
+ assert_equal(DUMMY_TAG2, w)
219
+ id3v2_prog_test(DUMMY_TAG2, w)
220
+ end
221
+
222
+ #test the tag with the "id3v2" program
223
+ def id3v2_prog_test(tag, written_tag)
224
+ return if RUBY_PLATFORM =~ /win32/
225
+ return if `which id3v2`.empty?
226
+ start = false
227
+ id3v2_output = {}
228
+ `id3v2 -l #{TEMP_FILE}`.split(/\n/).each do |line|
229
+ if m = /^(.{4}) \(.+\): (.+)$/.match(line)
230
+ k, v = m[1, 2]
231
+ case k
232
+ when "COMM"
233
+ v.sub!(/\(\)\[.{3}\]: (.+)/, '\1')
234
+ end
235
+ id3v2_output[k] = v
236
+ end
237
+ end
238
+
239
+ assert_equal( id3v2_output, written_tag, "id3v2 program output doesn't match")
240
+ end
241
+
242
+ def test_id3v2_trash
243
+ end
244
+
245
+ def test_id3v2_complex
246
+ tag = {}
247
+ #ID3v2::TAGS.keys.each do |k|
248
+ ["PRIV", "APIC"].each do |k|
249
+ tag[k] = random_string(50)
250
+ end
251
+
252
+ got_tag = write_tag2_to_temp_file(tag)
253
+ assert_equal(tag, got_tag)
254
+ end
255
+
256
+ def test_id3v2_bigtag
257
+ tag = {"APIC" => random_string(1024) }
258
+ assert_equal(tag, write_tag2_to_temp_file(tag))
259
+ end
260
+
261
+ def test_infinite_loop_on_seek_to_v2_end
262
+
263
+ end
264
+
265
+ def test_leading_char_gets_chopped
266
+ tag2 = DUMMY_TAG2.dup
267
+ tag2["WOAR"] = "http://foo.bar"
268
+ w = write_tag2_to_temp_file(tag2)
269
+ assert_equal("http://foo.bar", w["WOAR"])
270
+
271
+ system(%(id3v2 --WOAR "http://foo.bar" "#{TEMP_FILE}"))
272
+
273
+ Mp3Info.open(TEMP_FILE) do |mp3|
274
+ assert_equal "http://foo.bar", mp3.tag2["WOAR"]
275
+ end
276
+ end
277
+
278
+ def test_reading2_2_tags
279
+ File.open(TEMP_FILE, "w") { |f| f.write(@valid_mp3_2_2) }
280
+
281
+ Mp3Info.open(TEMP_FILE) do |mp3|
282
+ assert_equal "2.2.0", mp3.tag2.version
283
+ expected_tag = {
284
+ "TCO" => "Hip Hop/Rap",
285
+ "TP1" => "Grems Aka Supermicro",
286
+ "TT2" => "Intro",
287
+ "TAL" => "Air Max",
288
+ "TEN" => "iTunes v7.0.2.16",
289
+ "TYE" => "2006",
290
+ "TRK" => "1/17",
291
+ "TPA" => "1/1" }
292
+ tag = mp3.tag2.dup
293
+ assert_equal 4, tag["COM"].size
294
+ tag.delete("COM")
295
+ assert_equal expected_tag, tag
296
+
297
+ expected_tag = {
298
+ "genre_s" => "Hip Hop/Rap",
299
+ "title" => "Intro",
300
+ #"comments" => "\000engiTunPGAP\0000\000\000",
301
+ "comments" => "0",
302
+ "year" => 2006,
303
+ "album" => "Air Max",
304
+ "artist" => "Grems Aka Supermicro",
305
+ "tracknum" => 1 }
306
+ # test universal tag
307
+ assert_equal expected_tag, mp3.tag
308
+ end
309
+ end
310
+
311
+ def test_writing_universal_tag_from_2_2_tags
312
+ File.open(TEMP_FILE, "w") { |f| f.write(@valid_mp3_2_2) }
313
+ Mp3Info.open(TEMP_FILE) do |mp3|
314
+ mp3.tag.artist = "toto"
315
+ mp3.tag.comments = "comments"
316
+ mp3.flush
317
+ expected_tag = {
318
+ "artist" => "toto",
319
+ "genre_s" => "Hip Hop/Rap",
320
+ "title" => "Intro",
321
+ "comments" => "comments",
322
+ "year" => 2006,
323
+ "album" => "Air Max",
324
+ "tracknum" => 1}
325
+
326
+ assert_equal expected_tag, mp3.tag
327
+ end
328
+ end
329
+
330
+ def test_remove_tag
331
+ Mp3Info.open(TEMP_FILE) do |mp3|
332
+ tag = mp3.tag
333
+ tag.title = "title"
334
+ tag.artist = "artist"
335
+ mp3.close
336
+ mp3.reload
337
+ assert !mp3.tag1.empty?, "tag is empty"
338
+ mp3.removetag1
339
+ mp3.flush
340
+ assert mp3.tag1.empty?, "tag is not empty"
341
+ end
342
+ end
343
+
344
+ def test_good_parsing_of_a_pathname
345
+ fn = "Freak On `(Stone´s Club Mix).mp3"
346
+ FileUtils.cp(TEMP_FILE, fn)
347
+ begin
348
+ Mp3Info.open(fn) do |mp3|
349
+ mp3.tag.title = fn
350
+ mp3.flush
351
+ if RUBY_VERSION < "1.9.0"
352
+ assert_equal fn, mp3.tag.title
353
+ else
354
+ assert_equal fn, mp3.tag.title.force_encoding("utf-8")
355
+ end
356
+ end
357
+ ensure
358
+ File.delete(fn)
359
+ end
360
+ end
361
+
362
+ def test_validity_of_id3v2_options
363
+ info = Mp3Info.new(TEMP_FILE)
364
+ expected_hash = { :lang => "ENG", :encoding => "iso-8859-1" }
365
+ assert_equal( expected_hash, info.tag2.options)
366
+
367
+ assert_raises(ArgumentError) do
368
+ Mp3Info.new(TEMP_FILE, :encoding => "bad encoding")
369
+ end
370
+ end
371
+
372
+ def test_encoding_read
373
+ Mp3Info.open(TEMP_FILE) do |mp3|
374
+ mp3.tag2['TEST'] = "all\xe9"
375
+ end
376
+
377
+ Mp3Info.open(TEMP_FILE, :encoding => "utf-8") do |mp3|
378
+ assert_equal "allé", mp3.tag2['TEST']
379
+ end
380
+
381
+ Mp3Info.open(TEMP_FILE, :encoding => "iso-8859-1") do |mp3|
382
+ if RUBY_VERSION < "1.9.0"
383
+ assert_equal "all\xe9", mp3.tag2['TEST']
384
+ else
385
+ assert_equal "all\xe9".force_encoding("binary"), mp3.tag2['TEST']
386
+ end
387
+ end
388
+ end
389
+
390
+ def test_encoding_write
391
+ Mp3Info.open(TEMP_FILE, :encoding => 'utf-8') do |mp3|
392
+ mp3.tag2['TEST'] = "all\xc3\xa9"
393
+ end
394
+
395
+ Mp3Info.open(TEMP_FILE, :encoding => "iso-8859-1") do |mp3|
396
+ if RUBY_VERSION < "1.9.0"
397
+ assert_equal "all\xe9", mp3.tag2['TEST']
398
+ else
399
+ assert_equal "all\xe9".force_encoding("iso-8859-1"), mp3.tag2['TEST']
400
+ end
401
+ end
402
+ end
403
+
404
+ =begin
405
+ def test_should_raises_exception_when_writing_badly_encoded_frames
406
+ assert_raises(Iconv::Failure) do
407
+ Mp3Info.open(TEMP_FILE, :encoding => 'utf-8') do |mp3|
408
+ mp3.tag2['TEST'] = "all\xc3"
409
+ end
410
+ end
411
+ end
412
+ =end
413
+
414
+ def test_audio_content
415
+ require "digest/md5"
416
+
417
+ expected_digest = nil
418
+ Mp3Info.open(TEMP_FILE) do |mp3|
419
+ mp3.tag1.update(DUMMY_TAG1)
420
+ mp3.tag2.update(DUMMY_TAG2)
421
+ mp3.flush
422
+ assert mp3.hastag1?
423
+ assert mp3.hastag2?
424
+ assert mp3.tag2.io_position != 0
425
+ expected_digest = compute_audio_content_mp3_digest(mp3)
426
+ end
427
+
428
+ Mp3Info.open(TEMP_FILE) do |mp3|
429
+ mp3.removetag1
430
+ mp3.removetag2
431
+ mp3.flush
432
+ assert !mp3.hastag1?
433
+ assert !mp3.hastag2?
434
+ got_digest = compute_audio_content_mp3_digest(mp3)
435
+ assert_equal expected_digest, got_digest
436
+ end
437
+ end
438
+
439
+ def test_audio_content_problematic
440
+ File.open(TEMP_FILE, "w") { |f| f.write(FIXTURES["audio_content_fixture"]) }
441
+ Mp3Info.open(TEMP_FILE) do |mp3|
442
+ expected_pos = 150
443
+ audio_content_pos, audio_content_size = mp3.audio_content
444
+ assert_equal expected_pos, audio_content_pos
445
+ assert_equal File.size(TEMP_FILE) - expected_pos, audio_content_size
446
+ end
447
+ end
448
+
449
+ def test_headerless_vbr_file
450
+ mp3_length = 3
451
+ # this will generate a 15 sec mp3 file (44100hz*16bit*2channels) = 60/4 = 15
452
+ system("dd if=/dev/urandom bs=44100 count=#{mp3_length*4} 2>/dev/null | \
453
+ lame -v -m s --vbr-new --preset 128 -r -s 44.1 --bitwidth 16 - - > #{TEMP_FILE} 2>/dev/null")
454
+
455
+ Mp3Info.open(TEMP_FILE) do |mp3|
456
+ assert mp3.vbr
457
+ assert_in_delta(mp3_length, mp3.length, 0.1)
458
+ assert_in_delta(128, mp3.bitrate, 8)
459
+ end
460
+ end
461
+
462
+ def test_parse_tags_disabled
463
+ write_tag2_to_temp_file(DUMMY_TAG2)
464
+ Mp3Info.open(TEMP_FILE, :parse_tags => false) do |mp3|
465
+ assert mp3.tag.empty?
466
+ assert mp3.tag1.empty?
467
+ assert mp3.tag2.empty?
468
+ mp3.tag["artist"] = "some dummy tag"
469
+ mp3.tag2["TIT2"] = "title 2"
470
+ mp3.flush
471
+ # tag should not be written
472
+ assert mp3.tag.empty?
473
+ assert mp3.tag1.empty?
474
+ assert mp3.tag2.empty?
475
+ end
476
+ end
477
+
478
+ def test_string_io
479
+ io = load_string_io
480
+ Mp3Info.open(io) do |mp3|
481
+ assert_mp3_info_are_ok(mp3)
482
+ end
483
+ end
484
+
485
+ def test_trying_to_rename_a_stringio_should_raise_an_error
486
+ io = load_string_io
487
+ Mp3Info.open(io) do |mp3|
488
+ assert_raises(Mp3InfoError) do
489
+ mp3.rename("whatever_filename_is_error_should_be_raised.mp3")
490
+ end
491
+ end
492
+ end
493
+
494
+ def test_hastag_class_methods_with_a_stringio
495
+ Mp3Info.open(TEMP_FILE) do |info|
496
+ info.tag1 = @tag
497
+ end
498
+ io = load_string_io
499
+ assert(Mp3Info.hastag1?(io))
500
+
501
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
502
+ io = load_string_io
503
+ assert(Mp3Info.hastag2?(io))
504
+ end
505
+
506
+ def compute_audio_content_mp3_digest(mp3)
507
+ pos, size = mp3.audio_content
508
+ data = File.open(mp3.filename) do |f|
509
+ f.seek(pos, IO::SEEK_SET)
510
+ f.read(size)
511
+ end
512
+ Digest::MD5.new.update(data).hexdigest
513
+ end
514
+
515
+ def write_tag2_to_temp_file(tag)
516
+ Mp3Info.open(TEMP_FILE) do |mp3|
517
+ mp3.tag2.update(tag)
518
+ end
519
+ return Mp3Info.open(TEMP_FILE) { |m| m.tag2 }
520
+ #system("cp -v #{TEMP_FILE} #{TEMP_FILE}.test")
521
+ end
522
+
523
+ def random_string(size)
524
+ out = ""
525
+ size.times { out << rand(256).chr }
526
+ out
527
+ end
528
+
529
+ def assert_mp3_info_are_ok(mp3)
530
+ assert_equal(1, mp3.mpeg_version)
531
+ assert_equal(3, mp3.layer)
532
+ assert_equal(false, mp3.vbr)
533
+ assert_equal(128, mp3.bitrate)
534
+ assert_equal("JStereo", mp3.channel_mode)
535
+ assert_equal(44100, mp3.samplerate)
536
+ assert_equal(0.1305625, mp3.length)
537
+ assert_equal({:original => true,
538
+ :error_protection => false,
539
+ :padding => false,
540
+ :emphasis => 0,
541
+ :private => true,
542
+ :mode_extension => 2,
543
+ :copyright => false}, mp3.header)
544
+ end
545
+
546
+ def load_string_io(filename = TEMP_FILE)
547
+ io = StringIO.new
548
+ data = File.read(filename)
549
+ io.write(data)
550
+ io.rewind
551
+ io
552
+ end
553
+
554
+ =begin
555
+
556
+ def test_encoder
557
+ write_to_temp
558
+ info = Mp3Info.new(TEMP_FILE)
559
+ assert(info.encoder == "Lame 3.93")
560
+ end
561
+
562
+ def test_vbr
563
+ mp3_vbr = Base64.decode64 <<EOF
564
+
565
+ EOF
566
+ File.open(TEMP_FILE, "w") { |f| f.write(mp3_vbr) }
567
+ info = Mp3Info.new(TEMP_FILE)
568
+ assert_equal(info.vbr, true)
569
+ assert_equal(info.bitrate, 128)
570
+ end
571
+ =end
572
+ end