ruby-mp3info 0.5.1 → 0.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/{CHANGELOG → History.txt} +11 -15
- data/Manifest.txt +9 -0
- data/README.txt +78 -0
- data/Rakefile +18 -0
- data/install.rb +1022 -0
- data/lib/mp3info.rb +11 -9
- data/lib/mp3info/id3v2.rb +51 -32
- data/{test.rb → test/test_ruby-mp3info.rb} +61 -32
- metadata +59 -41
- data/EXAMPLES +0 -43
- data/README +0 -28
data/lib/mp3info.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: mp3info.rb
|
1
|
+
# $Id: mp3info.rb 64 2008-02-24 02:11:57Z moumar $
|
2
2
|
# License:: Ruby
|
3
3
|
# Author:: Guillaume Pierronnet (mailto:moumar_AT__rubyforge_DOT_org)
|
4
4
|
# Website:: http://ruby-mp3info.rubyforge.org/
|
@@ -18,7 +18,7 @@ end
|
|
18
18
|
|
19
19
|
class Mp3Info
|
20
20
|
|
21
|
-
VERSION = "0.
|
21
|
+
VERSION = "0.6"
|
22
22
|
|
23
23
|
LAYER = [ nil, 3, 2, 1]
|
24
24
|
BITRATE = [
|
@@ -161,14 +161,16 @@ class Mp3Info
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
# Instantiate
|
165
|
-
|
164
|
+
# Instantiate Mp3Info object with name +filename+ and an
|
165
|
+
# options hash for ID3v2#new underlying object
|
166
|
+
def initialize(filename, id3v2_options = {})
|
166
167
|
$stderr.puts("#{self.class}::new() does not take block; use #{self.class}::open() instead") if block_given?
|
167
168
|
@filename = filename
|
169
|
+
@id3v2_options = id3v2_options
|
168
170
|
reload
|
169
171
|
end
|
170
172
|
|
171
|
-
# reload the file from disk
|
173
|
+
# reload (or load for the first time) the file from disk
|
172
174
|
def reload
|
173
175
|
raise(Mp3InfoError, "empty file") unless File.size?(@filename)
|
174
176
|
@hastag1 = false
|
@@ -176,7 +178,7 @@ class Mp3Info
|
|
176
178
|
@tag1 = {}
|
177
179
|
@tag1.extend(HashKeys)
|
178
180
|
|
179
|
-
@tag2 = ID3v2.new
|
181
|
+
@tag2 = ID3v2.new(@id3v2_options)
|
180
182
|
|
181
183
|
@file = File.new(filename, "rb")
|
182
184
|
@file.extend(Mp3FileMethods)
|
@@ -283,8 +285,8 @@ class Mp3Info
|
|
283
285
|
end
|
284
286
|
|
285
287
|
# "block version" of Mp3Info::new()
|
286
|
-
def self.open(
|
287
|
-
m = self.new(
|
288
|
+
def self.open(*params)
|
289
|
+
m = self.new(*params)
|
288
290
|
ret = nil
|
289
291
|
if block_given?
|
290
292
|
begin
|
@@ -307,6 +309,7 @@ class Mp3Info
|
|
307
309
|
self
|
308
310
|
end
|
309
311
|
|
312
|
+
# Remove id3v2 from mp3
|
310
313
|
def removetag2
|
311
314
|
@tag2.clear
|
312
315
|
self
|
@@ -397,7 +400,6 @@ class Mp3Info
|
|
397
400
|
tempfile_name = @filename + ".tmp"
|
398
401
|
File.open(tempfile_name, "wb") do |tempfile|
|
399
402
|
unless @tag2.empty?
|
400
|
-
tempfile.write("ID3")
|
401
403
|
tempfile.write(@tag2.to_bin)
|
402
404
|
end
|
403
405
|
|
data/lib/mp3info/id3v2.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require "mp3info/extension_modules"
|
2
|
+
require "iconv"
|
2
3
|
|
3
4
|
# This class is not intended to be used directly
|
4
5
|
class ID3v2 < DelegateClass(Hash)
|
5
|
-
|
6
|
+
|
7
|
+
# Major version used when writing tags
|
8
|
+
WRITE_VERSION = 3
|
6
9
|
|
7
10
|
TAGS = {
|
8
11
|
"AENC" => "Audio encryption",
|
@@ -81,22 +84,33 @@ class ID3v2 < DelegateClass(Hash)
|
|
81
84
|
"WXXX" => "User defined URL link frame"
|
82
85
|
}
|
83
86
|
|
87
|
+
# See id3v2.4.0-structure document, at section 4.
|
88
|
+
TEXT_ENCODINGS = ["iso-8859-1", "utf-16", "utf-16be", "utf-8"]
|
89
|
+
|
84
90
|
include Mp3Info::HashKeys
|
85
91
|
|
86
92
|
attr_reader :io_position
|
87
93
|
|
88
|
-
#
|
89
|
-
#
|
90
|
-
# :+encoding+:
|
94
|
+
# :+lang+: for writing comments
|
95
|
+
#
|
96
|
+
# :+encoding+: one of the string of +TEXT_ENCODINGS+,
|
97
|
+
# used as a source and destination encoding respectively
|
98
|
+
# for read and write tag2 values.
|
91
99
|
attr_reader :options
|
92
100
|
|
93
101
|
def initialize(options = {})
|
94
102
|
@options = {
|
95
|
-
:lang => "ENG",
|
96
|
-
:encoding =>
|
103
|
+
:lang => "ENG",
|
104
|
+
:encoding => "iso-8859-1"
|
97
105
|
}
|
106
|
+
|
98
107
|
@options.update(options)
|
108
|
+
@text_encoding_index = TEXT_ENCODINGS.index(@options[:encoding])
|
99
109
|
|
110
|
+
unless @text_encoding_index
|
111
|
+
raise(ArgumentError, "bad id3v2 text encoding specified")
|
112
|
+
end
|
113
|
+
|
100
114
|
@hash = {}
|
101
115
|
#TAGS.keys.each { |k| @hash[k] = nil }
|
102
116
|
@hash_orig = {}
|
@@ -105,19 +119,22 @@ class ID3v2 < DelegateClass(Hash)
|
|
105
119
|
@version_maj = @version_min = nil
|
106
120
|
end
|
107
121
|
|
122
|
+
# does this tag correctly read ?
|
108
123
|
def valid?
|
109
124
|
@valid
|
110
125
|
end
|
111
126
|
|
127
|
+
# does this tag has been changed ?
|
112
128
|
def changed?
|
113
129
|
@hash_orig != @hash
|
114
130
|
end
|
115
131
|
|
132
|
+
# full version of this tag (like 2.3.0)
|
116
133
|
def version
|
117
134
|
"2.#{@version_maj}.#{@version_min}"
|
118
135
|
end
|
119
136
|
|
120
|
-
### gets id3v2 tag information from io
|
137
|
+
### gets id3v2 tag information from io object (must support #seek() method)
|
121
138
|
def from_io(io)
|
122
139
|
@io = io
|
123
140
|
version_maj, version_min, flags = @io.read(3).unpack("CCB4")
|
@@ -142,6 +159,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
142
159
|
# we should now have io sitting at the first MPEG frame
|
143
160
|
end
|
144
161
|
|
162
|
+
# dump tag for writing. Version is always 2.#{WRITE_VERSION}.0.
|
145
163
|
def to_bin
|
146
164
|
#TODO handle of @tag2[TLEN"]
|
147
165
|
#TODO add of crc
|
@@ -151,7 +169,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
151
169
|
@hash.each do |k, v|
|
152
170
|
next unless v
|
153
171
|
next if v.respond_to?("empty?") and v.empty?
|
154
|
-
data = encode_tag(k, v.to_s)
|
172
|
+
data = encode_tag(k, v.to_s, WRITE_VERSION)
|
155
173
|
#data << "\x00"*2 #End of tag
|
156
174
|
|
157
175
|
tag << k[0,4] #4 characte max for a tag's key
|
@@ -161,9 +179,9 @@ class ID3v2 < DelegateClass(Hash)
|
|
161
179
|
tag << data
|
162
180
|
end
|
163
181
|
|
164
|
-
tag_str = ""
|
182
|
+
tag_str = "ID3"
|
165
183
|
#version_maj, version_min, unsync, ext_header, experimental, footer
|
166
|
-
tag_str << [
|
184
|
+
tag_str << [ WRITE_VERSION, 0, "0000" ].pack("CCB4")
|
167
185
|
tag_str << to_syncsafe(tag.size)
|
168
186
|
tag_str << tag
|
169
187
|
p tag_str if $DEBUG
|
@@ -172,21 +190,26 @@ class ID3v2 < DelegateClass(Hash)
|
|
172
190
|
|
173
191
|
private
|
174
192
|
|
193
|
+
def encode_tag(name, value, version)
|
194
|
+
puts "encode_tag(#{name.inspect}, #{value.inspect}, #{version})" if $DEBUG
|
195
|
+
|
196
|
+
text_encoding_index = @text_encoding_index
|
197
|
+
if version == 3
|
198
|
+
# in id3v2.3 tags, there is only 2 encodings possible
|
199
|
+
transcoded_value = value
|
200
|
+
if text_encoding_index >= 2
|
201
|
+
transcoded_value = Iconv.iconv(TEXT_ENCODINGS[1], TEXT_ENCODINGS[text_encoding_index], value)[0]
|
202
|
+
text_encoding_index = 1
|
203
|
+
end
|
204
|
+
end
|
175
205
|
|
176
|
-
def encode_tag(name, value)
|
177
|
-
puts "encode_tag(#{name.inspect}, #{value.inspect})" if $DEBUG
|
178
206
|
case name
|
179
207
|
when "COMM"
|
180
|
-
[
|
181
|
-
when /^W/ # URL link frames
|
208
|
+
[ text_encoding_index , @options[:lang], 0, transcoded_value ].pack("ca3ca*")
|
209
|
+
when "UFID", /^W/ # URL link frames
|
182
210
|
value
|
183
211
|
else
|
184
|
-
|
185
|
-
"\x00"+value
|
186
|
-
else
|
187
|
-
"\x01"+value #Iconv.iconv("UNICODE", "ISO-8859-1", value)[0]
|
188
|
-
end
|
189
|
-
#data << "\x00"
|
212
|
+
text_encoding_index.chr + transcoded_value
|
190
213
|
end
|
191
214
|
end
|
192
215
|
|
@@ -197,22 +220,18 @@ class ID3v2 < DelegateClass(Hash)
|
|
197
220
|
#FIXME improve this
|
198
221
|
encoding, lang, str = value.unpack("ca3a*")
|
199
222
|
out = value.split(0.chr).last
|
200
|
-
when /^W/ # URL link frames
|
223
|
+
when "UFID", /^W/ # URL link frames
|
201
224
|
out = value
|
202
225
|
else
|
203
|
-
encoding = value[0] # language encoding
|
226
|
+
encoding = value[0] # language encoding (see TEXT_ENCODINGS constant)
|
204
227
|
out = value[1..-1]
|
205
228
|
end
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
out[
|
212
|
-
begin
|
213
|
-
out = Iconv.iconv("ISO-8859-1", "UTF-16", out)[0]
|
214
|
-
rescue Iconv::IllegalSequence, Iconv::InvalidCharacter
|
215
|
-
end
|
229
|
+
|
230
|
+
printf("encoding: %d, value: %s\n", encoding, value.inspect) if $DEBUG
|
231
|
+
# we need to convert the string in order to match
|
232
|
+
# the requested encoding
|
233
|
+
if encoding && encoding != @text_encoding_index
|
234
|
+
out = Iconv.iconv(@options[:encoding], TEXT_ENCODINGS[encoding], out)[0]
|
216
235
|
end
|
217
236
|
out
|
218
237
|
end
|
@@ -21,10 +21,6 @@ class Mp3InfoTest < Test::Unit::TestCase
|
|
21
21
|
"TRCK" => "tracknum"
|
22
22
|
}
|
23
23
|
|
24
|
-
# aliasing to allow testing with old versions of Test::Unit
|
25
|
-
alias set_up setup
|
26
|
-
alias tear_down teardown
|
27
|
-
|
28
24
|
def setup
|
29
25
|
# Command to create a dummy MP3
|
30
26
|
# dd if=/dev/zero bs=1024 count=15 | lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - - | ruby -rbase64 -e 'print Base64.encode64($stdin.read)'
|
@@ -94,7 +90,6 @@ EOF
|
|
94
90
|
FileUtils.rm_f(TEMP_FILE)
|
95
91
|
end
|
96
92
|
|
97
|
-
|
98
93
|
def test_to_s
|
99
94
|
Mp3Info.open(TEMP_FILE) { |info| assert(info.to_s.is_a?(String)) }
|
100
95
|
end
|
@@ -104,15 +99,15 @@ EOF
|
|
104
99
|
str = "0"*1024*1024
|
105
100
|
f.write(str)
|
106
101
|
end
|
107
|
-
assert_raises(Mp3InfoError)
|
102
|
+
assert_raises(Mp3InfoError) do
|
108
103
|
mp3 = Mp3Info.new(TEMP_FILE)
|
109
|
-
|
104
|
+
end
|
110
105
|
end
|
111
106
|
|
112
107
|
def test_is_an_mp3
|
113
|
-
assert_nothing_raised
|
108
|
+
assert_nothing_raised do
|
114
109
|
Mp3Info.new(TEMP_FILE).close
|
115
|
-
|
110
|
+
end
|
116
111
|
end
|
117
112
|
|
118
113
|
def test_detected_info
|
@@ -129,7 +124,7 @@ EOF
|
|
129
124
|
end
|
130
125
|
|
131
126
|
def test_vbr_mp3_length
|
132
|
-
temp_file_vbr = File.join(File.dirname($0), "
|
127
|
+
temp_file_vbr = File.join(File.dirname($0), "test_vbr_length.mp3")
|
133
128
|
|
134
129
|
unless File.exists?(temp_file_vbr)
|
135
130
|
tempfile = Tempfile.new("ruby-mp3info_test")
|
@@ -235,7 +230,7 @@ EOF
|
|
235
230
|
|
236
231
|
def test_id3v2_version
|
237
232
|
written_tag = write_temp_file(BASIC_TAG2)
|
238
|
-
assert_equal( "2.
|
233
|
+
assert_equal( "2.#{ID3v2::WRITE_VERSION}.0", written_tag.version )
|
239
234
|
end
|
240
235
|
|
241
236
|
def test_id3v2_methods
|
@@ -254,6 +249,30 @@ EOF
|
|
254
249
|
id3v2_prog_test(BASIC_TAG2, w)
|
255
250
|
end
|
256
251
|
|
252
|
+
#test the tag with the "id3v2" program
|
253
|
+
def id3v2_prog_test(tag, written_tag)
|
254
|
+
return if RUBY_PLATFORM =~ /win32/
|
255
|
+
return if `which id3v2`.empty?
|
256
|
+
start = false
|
257
|
+
id3v2_output = {}
|
258
|
+
`id3v2 -l #{TEMP_FILE}`.each do |line|
|
259
|
+
if line =~ /^id3v2 tag info/
|
260
|
+
start = true
|
261
|
+
next
|
262
|
+
end
|
263
|
+
next unless start
|
264
|
+
k, v = /^(.{4}) \(.+\): (.+)$/.match(line)[1,2]
|
265
|
+
case k
|
266
|
+
#COMM (Comments): ()[spa]: fmg
|
267
|
+
when "COMM"
|
268
|
+
v.sub!(/\(\)\[.{3}\]: (.+)/, '\1')
|
269
|
+
end
|
270
|
+
id3v2_output[k] = v
|
271
|
+
end
|
272
|
+
|
273
|
+
assert_equal( id3v2_output, written_tag, "id3v2 program output doesn't match")
|
274
|
+
end
|
275
|
+
|
257
276
|
def test_id3v2_trash
|
258
277
|
end
|
259
278
|
|
@@ -319,7 +338,7 @@ EOF
|
|
319
338
|
# end
|
320
339
|
|
321
340
|
def test_good_parsing_of_a_pathname
|
322
|
-
fn = "Freak On `(Stone
|
341
|
+
fn = "Freak On `(Stone´s Club Mix).mp3"
|
323
342
|
File.rename(TEMP_FILE, fn)
|
324
343
|
begin
|
325
344
|
mp3 = Mp3Info.new(fn)
|
@@ -333,28 +352,38 @@ EOF
|
|
333
352
|
end
|
334
353
|
end
|
335
354
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
if line =~ /^id3v2 tag info/
|
344
|
-
start = true
|
345
|
-
next
|
346
|
-
end
|
347
|
-
next unless start
|
348
|
-
k, v = /^(.{4}) \(.+\): (.+)$/.match(line)[1,2]
|
349
|
-
case k
|
350
|
-
#COMM (Comments): ()[spa]: fmg
|
351
|
-
when "COMM"
|
352
|
-
v.sub!(/\(\)\[.{3}\]: (.+)/, '\1')
|
353
|
-
end
|
354
|
-
id3v2_output[k] = v
|
355
|
+
def test_validity_of_id3v2_options
|
356
|
+
info = Mp3Info.new(TEMP_FILE)
|
357
|
+
expected_hash = { :lang => "ENG", :encoding => "iso-8859-1" }
|
358
|
+
assert_equal( expected_hash, info.tag2.options)
|
359
|
+
|
360
|
+
assert_raises(ArgumentError) do
|
361
|
+
Mp3Info.new(TEMP_FILE, :encoding => "bad encoding")
|
355
362
|
end
|
363
|
+
end
|
356
364
|
|
357
|
-
|
365
|
+
def test_encoding_read
|
366
|
+
Mp3Info.open(TEMP_FILE) do |mp3|
|
367
|
+
mp3.tag2['TEST'] = "all\xe9"
|
368
|
+
end
|
369
|
+
|
370
|
+
Mp3Info.open(TEMP_FILE, :encoding => "utf-8") do |mp3|
|
371
|
+
assert_equal "all\xc3\xa9", mp3.tag2['TEST']
|
372
|
+
end
|
373
|
+
|
374
|
+
Mp3Info.open(TEMP_FILE, :encoding => "iso-8859-1") do |mp3|
|
375
|
+
assert_equal "all\xe9", mp3.tag2['TEST']
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_encoding_write
|
380
|
+
Mp3Info.open(TEMP_FILE, :encoding => 'utf-8') do |mp3|
|
381
|
+
mp3.tag2['TEST'] = "all\xc3\xa9"
|
382
|
+
end
|
383
|
+
|
384
|
+
Mp3Info.open(TEMP_FILE, :encoding => "iso-8859-1") do |mp3|
|
385
|
+
assert_equal "all\xe9", mp3.tag2['TEST']
|
386
|
+
end
|
358
387
|
end
|
359
388
|
|
360
389
|
def write_temp_file(tag)
|
metadata
CHANGED
@@ -1,54 +1,72 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.2
|
3
|
-
specification_version: 1
|
4
2
|
name: ruby-mp3info
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-09-10 00:00:00 +02:00
|
8
|
-
summary: ruby-mp3info is a pure-ruby library to retrieve low level informations on mp3 files and manipulate id3v1 and id3v2 tags
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: moumar@rubyforge.org
|
12
|
-
homepage: http://ruby-mp3info.rubyforge.org
|
13
|
-
rubyforge_project: ruby-mp3info
|
14
|
-
description:
|
15
|
-
autorequire: mp3info
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: "0.6"
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Guillaume Pierronnet
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
- EXAMPLES
|
35
|
-
- test.rb
|
36
|
-
- lib/mp3info.rb
|
37
|
-
- lib/mp3info/extension_modules.rb
|
38
|
-
- lib/mp3info/id3v2.rb
|
39
|
-
test_files: []
|
40
|
-
|
41
|
-
rdoc_options: []
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
42
11
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
-
|
12
|
+
date: 2008-02-24 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.5.0
|
23
|
+
version:
|
24
|
+
description: "* written in pure ruby * read low-level informations like bitrate, length, samplerate, etc... * read, write, remove id3v1 and id3v2 tags * only 2.3 version is supported for writings id3v2 tags == SYNOPSIS: a good exercise is to read the test.rb to understand how the library works deeper require \"mp3info\" # read and display infos & tags Mp3Info.open(\"myfile.mp3\") do |mp3info| puts mp3info end # read/write tag1 and tag2 with Mp3Info#tag attribute # when reading tag2 have priority over tag1 # when writing, each tag is written. Mp3Info.open(\"myfile.mp3\") do |mp3| puts mp3.tag.title puts mp3.tag.artist puts mp3.tag.album puts mp3.tag.tracknum mp3.tag.title = \"track title\" mp3.tag.artist = \"artist name\" end Mp3Info.open(\"myfile.mp3\") do |mp3| # you can access four letter v2 tags like this puts mp3.tag2.TIT2 mp3.tag2.TIT2 = \"new TIT2\" # or like that mp3.tag2[\"TIT2\"] # at this time, only COMM tag is processed after reading and before writing # according to ID3v2#options hash mp3.tag2.options[:lang] = \"FRE\" mp3.tag2.COMM = \"my comment in french, correctly handled when reading and writing\" end"
|
25
|
+
email: moumar@rubyforge.org
|
47
26
|
executables: []
|
48
27
|
|
49
28
|
extensions: []
|
50
29
|
|
30
|
+
extra_rdoc_files:
|
31
|
+
- History.txt
|
32
|
+
- Manifest.txt
|
33
|
+
- README.txt
|
34
|
+
files:
|
35
|
+
- History.txt
|
36
|
+
- Manifest.txt
|
37
|
+
- README.txt
|
38
|
+
- Rakefile
|
39
|
+
- install.rb
|
40
|
+
- lib/mp3info.rb
|
41
|
+
- lib/mp3info/extension_modules.rb
|
42
|
+
- lib/mp3info/id3v2.rb
|
43
|
+
- test/test_ruby-mp3info.rb
|
44
|
+
has_rdoc: true
|
45
|
+
homepage:
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --main
|
49
|
+
- README.txt
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
51
64
|
requirements: []
|
52
65
|
|
53
|
-
|
54
|
-
|
66
|
+
rubyforge_project: ruby-mp3info
|
67
|
+
rubygems_version: 1.0.1
|
68
|
+
signing_key:
|
69
|
+
specification_version: 2
|
70
|
+
summary: ruby-mp3info is a pure-ruby library to retrieve low level informations on mp3 files and manipulate id3v1 and id3v2 tags
|
71
|
+
test_files:
|
72
|
+
- test/test_ruby-mp3info.rb
|