ruby-mp3info 0.8.9 → 0.8.10
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.
- checksums.yaml +4 -4
- data/History.txt +4 -0
- data/lib/mp3info.rb +1 -1
- data/lib/mp3info/extension_modules.rb +18 -45
- data/lib/mp3info/id3v2.rb +69 -80
- metadata +6 -8
- data/.gemtest +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec6e84b6d95639a26f8ff0baf64625889bfd6b3a
|
4
|
+
data.tar.gz: 9de4508c025b0c865f0eb4b29fe9c70b75495ed2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f619a8973e5dee36135546d5be127c9a9d105e255cd94323ce073ec58f03aa4e668dcc156398984c5ab4a9a756dd8ea9006cadab62e2824a3741c6a6f20a6d77
|
7
|
+
data.tar.gz: 171267103c889d7a3136e5f727a74db06acc664d5d7a5118e9cfb011abe0daa2165d06d1b71f2d4edd77ff6b8f4669d306c94a256ade3c6f7b4093e1eb5e9629
|
data/History.txt
CHANGED
data/lib/mp3info.rb
CHANGED
@@ -17,19 +17,7 @@ class Mp3Info
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
class ::String
|
21
|
-
if RUBY_VERSION < "1.9.0"
|
22
|
-
alias getbyte []
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
20
|
module Mp3FileMethods #:nodoc:
|
27
|
-
if RUBY_VERSION < "1.9.0"
|
28
|
-
def getbyte
|
29
|
-
getc
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
21
|
def get32bits
|
34
22
|
(getbyte << 24) + (getbyte << 16) + (getbyte << 8) + getbyte
|
35
23
|
end
|
@@ -41,26 +29,15 @@ class Mp3Info
|
|
41
29
|
|
42
30
|
class EncodingHelper #:nodoc:
|
43
31
|
def self.convert_to(value, from, to)
|
44
|
-
if
|
45
|
-
|
46
|
-
to = to + "//TRANSLIT"
|
47
|
-
end
|
48
|
-
ruby_18_encode(from, to, value)
|
32
|
+
if to == "utf-16"
|
33
|
+
("\uFEFF" + value).encode("UTF-16LE") # Chab 01.apr.2012 : moved from big to little endian for more compatibility (Windows Media Player, older Quicktime..)
|
49
34
|
else
|
50
|
-
|
51
|
-
("\uFEFF" + value).encode("UTF-16LE") # Chab 01.apr.2012 : moved from big to little endian for more compatibility (Windows Media Player, older Quicktime..)
|
52
|
-
else
|
53
|
-
value.encode(to)
|
54
|
-
end
|
35
|
+
value.encode(to)
|
55
36
|
end
|
56
37
|
end
|
57
38
|
|
58
39
|
def self.convert_from_iso_8859_1(value)
|
59
|
-
|
60
|
-
ruby_18_encode("utf-8", "iso-8859-1", value)
|
61
|
-
else
|
62
|
-
value.force_encoding("iso-8859-1").encode("utf-8")
|
63
|
-
end
|
40
|
+
value.force_encoding("iso-8859-1").encode("utf-8")
|
64
41
|
end
|
65
42
|
|
66
43
|
def self.ruby_18_encode(from, to, value)
|
@@ -68,26 +45,22 @@ class Mp3Info
|
|
68
45
|
end
|
69
46
|
|
70
47
|
def self.decode_utf16(out)
|
71
|
-
|
72
|
-
|
48
|
+
# String#bytes is not an array in Ruby 1.9
|
49
|
+
bytes = out.bytes.to_a
|
50
|
+
if out.length >= 2 and bytes[0] == 0xff and bytes[1] == 0xfe
|
51
|
+
tag_encoding = "UTF-16LE"
|
52
|
+
first_valid = 1
|
53
|
+
elsif out.length >= 2 and bytes[0] == 0xfe and bytes[1] == 0xff
|
54
|
+
tag_encoding = "UTF-16BE"
|
55
|
+
first_valid = 1
|
73
56
|
else
|
74
|
-
#
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
elsif out.length >= 2 and bytes[0] == 0xfe and bytes[1] == 0xff
|
80
|
-
tag_encoding = "UTF-16BE"
|
81
|
-
first_valid = 1
|
82
|
-
else
|
83
|
-
# ID3v2.3.0 section 3.3 mandates a BOM but some software
|
84
|
-
# erroneously omits it so we have to guess. Since most of
|
85
|
-
# the world is little endian we might as well go with that.
|
86
|
-
tag_encoding = "UTF-16LE"
|
87
|
-
first_valid = 0
|
88
|
-
end
|
89
|
-
out = out.dup.force_encoding(tag_encoding)[first_valid..-1]
|
57
|
+
# ID3v2.3.0 section 3.3 mandates a BOM but some software
|
58
|
+
# erroneously omits it so we have to guess. Since most of
|
59
|
+
# the world is little endian we might as well go with that.
|
60
|
+
tag_encoding = "UTF-16LE"
|
61
|
+
first_valid = 0
|
90
62
|
end
|
63
|
+
out = out.dup.force_encoding(tag_encoding)[first_valid..-1]
|
91
64
|
end
|
92
65
|
end
|
93
66
|
end
|
data/lib/mp3info/id3v2.rb
CHANGED
@@ -4,13 +4,6 @@
|
|
4
4
|
|
5
5
|
require "delegate"
|
6
6
|
|
7
|
-
if RUBY_VERSION[0..2] == "1.8"
|
8
|
-
require "iconv"
|
9
|
-
RUBY_1_8 = true
|
10
|
-
else
|
11
|
-
RUBY_1_8 = false
|
12
|
-
end
|
13
|
-
|
14
7
|
require "mp3info/extension_modules"
|
15
8
|
|
16
9
|
class ID3v2Error < StandardError ; end
|
@@ -19,8 +12,8 @@ class ID3v2Error < StandardError ; end
|
|
19
12
|
# It works like a hash, where key represents the tag name as 3 or 4 upper case letters
|
20
13
|
# (respectively related to 2.2 and 2.3+ tag) and value represented as array or raw value.
|
21
14
|
# Written version is always 2.3.
|
22
|
-
class ID3v2 < DelegateClass(Hash)
|
23
|
-
|
15
|
+
class ID3v2 < DelegateClass(Hash)
|
16
|
+
|
24
17
|
TAGS = {
|
25
18
|
"AENC" => "Audio encryption",
|
26
19
|
"APIC" => "Attached picture",
|
@@ -168,17 +161,17 @@ class ID3v2 < DelegateClass(Hash)
|
|
168
161
|
|
169
162
|
# In Ruby 2.1.0 (and possibly others), DelegateClass breaks Kernel methods.
|
170
163
|
include Kernel
|
171
|
-
|
164
|
+
|
172
165
|
# this is the position in the file where the tag really ends
|
173
166
|
attr_reader :io_position
|
174
167
|
|
175
168
|
# :+lang+: for writing comments
|
176
169
|
#
|
177
|
-
# [DEPRECATION] :+encoding+: one of the string of +TEXT_ENCODINGS+,
|
170
|
+
# [DEPRECATION] :+encoding+: one of the string of +TEXT_ENCODINGS+,
|
178
171
|
# use of :encoding parameter is DEPRECATED. In ruby 1.8, use utf-8 encoded strings for tags.
|
179
172
|
# In ruby >= 1.9, strings are automatically transcoded from their originaloriginal encoding.
|
180
173
|
attr_reader :options
|
181
|
-
|
174
|
+
|
182
175
|
# possible options are described above ('options' attribute)
|
183
176
|
# you can access this object like an hash, with [] and []= methods
|
184
177
|
# special cases are ["disc_number"] and ["disc_total"] mirroring TPOS attribute
|
@@ -208,7 +201,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
208
201
|
def changed?
|
209
202
|
@hash_orig != @hash
|
210
203
|
end
|
211
|
-
|
204
|
+
|
212
205
|
# full version of this tag (like "2.3.0") or nil
|
213
206
|
# if tag was not correctly read
|
214
207
|
def version
|
@@ -237,14 +230,14 @@ class ID3v2 < DelegateClass(Hash)
|
|
237
230
|
end
|
238
231
|
|
239
232
|
### ID3V2::add_picture
|
240
|
-
### Takes an image string as input and writes it with header.
|
233
|
+
### Takes an image string as input and writes it with header.
|
241
234
|
### Mime type is automatically guessed by default.
|
242
235
|
### It is possible but not necessary to include:
|
243
236
|
### :pic_type => 0 - 14 (see http://id3.org/id3v2.3.0#Attached_picture)
|
244
|
-
### :mime => 'gif'
|
237
|
+
### :mime => 'gif'
|
245
238
|
### :description => "Image description"
|
246
239
|
def add_picture(data, opts = {})
|
247
|
-
options = {
|
240
|
+
options = {
|
248
241
|
:pic_type => 0,
|
249
242
|
:mime => nil,
|
250
243
|
:description => "image"
|
@@ -282,7 +275,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
282
275
|
apic_images.each_index do |index|
|
283
276
|
pic = apic_images[index]
|
284
277
|
next if !pic.is_a?(String) or pic == ""
|
285
|
-
pic.force_encoding 'BINARY'
|
278
|
+
pic.force_encoding 'BINARY'
|
286
279
|
picture = []
|
287
280
|
jpg_regexp = Regexp.new("jpg|JPG|jpeg|JPEG".force_encoding("BINARY"),
|
288
281
|
Regexp::FIXEDENCODING )
|
@@ -290,7 +283,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
290
283
|
Regexp::FIXEDENCODING )
|
291
284
|
header = pic.unpack('a120').first.force_encoding "BINARY"
|
292
285
|
mime_pos = 0
|
293
|
-
|
286
|
+
|
294
287
|
# safest way to correctly extract jpg and png is finding mime
|
295
288
|
if header.match jpg_regexp and not header.match png_regexp
|
296
289
|
mime = "jpg"
|
@@ -300,7 +293,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
300
293
|
start_with_anchor = Regexp.new("^\xFF\xD8".force_encoding("BINARY"),
|
301
294
|
Regexp::FIXEDENCODING )
|
302
295
|
end
|
303
|
-
|
296
|
+
|
304
297
|
if header.match png_regexp and not header.match jpg_regexp
|
305
298
|
mime = "png"
|
306
299
|
mime_pos = header =~ png_regexp
|
@@ -309,7 +302,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
309
302
|
start_with_anchor = Regexp.new("^\x89PNG".force_encoding("BINARY"),
|
310
303
|
Regexp::FIXEDENCODING )
|
311
304
|
end
|
312
|
-
|
305
|
+
|
313
306
|
puts "analysing image: #{header.inspect}..." if $DEBUG
|
314
307
|
_, _, desc, data = pic[mime_pos, pic.length].unpack('Z*hZ*a*')
|
315
308
|
|
@@ -318,10 +311,10 @@ class ID3v2 < DelegateClass(Hash)
|
|
318
311
|
real_start = pic =~ start
|
319
312
|
data = pic[real_start, pic.length]
|
320
313
|
end
|
321
|
-
|
314
|
+
|
322
315
|
if mime == "jpg"
|
323
316
|
# inspect jpg image header (first 10 chars) for "\xFF\x00" (expect "\xFF")
|
324
|
-
trailing_null_byte = Regexp.new("(\377)(\000)".force_encoding('BINARY'),
|
317
|
+
trailing_null_byte = Regexp.new("(\377)(\000)".force_encoding('BINARY'),
|
325
318
|
Regexp::FIXEDENCODING)
|
326
319
|
md = data =~ trailing_null_byte
|
327
320
|
if !md.nil? and md < 10
|
@@ -335,7 +328,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
335
328
|
end
|
336
329
|
|
337
330
|
filename = ("%02i_#{desc[0,25]}" % (index + 1)).gsub('/','')
|
338
|
-
|
331
|
+
|
339
332
|
picture[0] = filename
|
340
333
|
picture[1] = data
|
341
334
|
result << picture
|
@@ -346,7 +339,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
346
339
|
def inspect
|
347
340
|
self.to_inspect_hash
|
348
341
|
end
|
349
|
-
|
342
|
+
|
350
343
|
def remove_pictures
|
351
344
|
self["APIC"] = ""
|
352
345
|
self["PIC"] = ""
|
@@ -362,7 +355,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
362
355
|
raise(ID3v2Error, "can't find version_maj ('#{version_maj}')") unless [2, 3, 4].include?(version_maj)
|
363
356
|
@version_maj, @version_min = version_maj, version_min
|
364
357
|
@tag_length = @io.get_syncsafe
|
365
|
-
|
358
|
+
|
366
359
|
@parsed = true
|
367
360
|
begin
|
368
361
|
case @version_maj
|
@@ -409,9 +402,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
409
402
|
tag << k[0,4] #4 characte max for a tag's key
|
410
403
|
#tag << to_syncsafe(data.size) #+1 because of the language encoding byte
|
411
404
|
size = data.size
|
412
|
-
|
413
|
-
size = data.dup.force_encoding("binary").size
|
414
|
-
end
|
405
|
+
size = data.dup.force_encoding("binary").size
|
415
406
|
tag << [size].pack("N") #+1 because of the language encoding byte
|
416
407
|
tag << "\x00"*2 #flags
|
417
408
|
tag << data
|
@@ -442,9 +433,8 @@ class ID3v2 < DelegateClass(Hash)
|
|
442
433
|
s = [ 1, @options[:lang], "\xFE\xFF\x00\x00", transcoded_value].pack("ca3a*a*")
|
443
434
|
return s
|
444
435
|
when /^T/
|
445
|
-
|
446
|
-
|
447
|
-
end
|
436
|
+
transcoded_value.force_encoding("BINARY")
|
437
|
+
|
448
438
|
return "\x01" + transcoded_value
|
449
439
|
else
|
450
440
|
return value
|
@@ -455,55 +445,55 @@ class ID3v2 < DelegateClass(Hash)
|
|
455
445
|
def decode_tag(name, raw_value)
|
456
446
|
puts("decode_tag(#{name.inspect}, #{raw_value.inspect})") if $DEBUG
|
457
447
|
if name =~ /^(T|COM|USLT)/
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
=
|
468
|
-
|
469
|
-
|
470
|
-
|
448
|
+
begin
|
449
|
+
if name =~ /^(COM|USLT)/
|
450
|
+
encoding_index, lang, raw_tag = raw_value.unpack("ca3a*")
|
451
|
+
if raw_tag == "\x00"
|
452
|
+
return nil
|
453
|
+
else
|
454
|
+
if encoding_index == 1
|
455
|
+
split_str = /\x00\x00\x00?/
|
456
|
+
else
|
457
|
+
split_str = "\x00"
|
458
|
+
end
|
459
|
+
head, tail = raw_tag.split(split_str)
|
460
|
+
if head == "\xFF\xFE".force_encoding('binary')
|
461
|
+
rgx = Regexp.new("^\xFF\xFE\x00\x00".force_encoding("BINARY"))
|
462
|
+
out = raw_tag.sub(rgx, '')
|
463
|
+
elsif tail
|
464
|
+
out = tail
|
465
|
+
elsif head
|
466
|
+
out = head
|
467
|
+
else
|
468
|
+
warn("warning: cannot decode tag #{name} with raw value #{raw_value.inspect}")
|
469
|
+
return nil
|
470
|
+
end
|
471
|
+
end
|
472
|
+
puts "COM tag found. encoding: #{encoding_index} lang: #{lang} str: #{out.inspect}" if $DEBUG
|
471
473
|
else
|
472
|
-
|
474
|
+
encoding_index = raw_value.getbyte(0) # language encoding (see TEXT_ENCODINGS constant)
|
475
|
+
out = raw_value[1..-1]
|
473
476
|
end
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
out = raw_value[1..-1]
|
478
|
-
end
|
479
|
-
# we need to convert the string in order to match
|
480
|
-
# the requested encoding
|
481
|
-
if encoding_index && TEXT_ENCODINGS[encoding_index] && out
|
482
|
-
if RUBY_1_8
|
483
|
-
out = Mp3Info::EncodingHelper.convert_to(out, TEXT_ENCODINGS[encoding_index], "utf-8")
|
484
|
-
else
|
477
|
+
# we need to convert the string in order to match
|
478
|
+
# the requested encoding
|
479
|
+
if TEXT_ENCODINGS[encoding_index]
|
485
480
|
if encoding_index == 1
|
486
481
|
out = Mp3Info::EncodingHelper.decode_utf16(out)
|
487
482
|
else
|
488
483
|
out.force_encoding(TEXT_ENCODINGS[encoding_index])
|
489
484
|
end
|
490
|
-
|
491
|
-
out.encode!("utf-8")
|
492
|
-
end
|
485
|
+
out.encode!("utf-8")
|
493
486
|
end
|
494
|
-
end
|
495
487
|
|
496
|
-
if out
|
497
488
|
# remove padding zeros for textual tags
|
498
|
-
|
499
|
-
|
500
|
-
else
|
501
|
-
r = Regexp.new("\x00*$".encode(out.encoding))
|
502
|
-
end
|
503
|
-
out.sub!(r, '')
|
504
|
-
end
|
489
|
+
r = Regexp.new("\x00*$".encode(out.encoding))
|
490
|
+
out.sub!(r, '')
|
505
491
|
|
506
|
-
|
492
|
+
return out
|
493
|
+
rescue => e
|
494
|
+
warn "warning: cannot decode tag #{name} with raw value #{raw_value.inspect}: #{e}"
|
495
|
+
return nil
|
496
|
+
end
|
507
497
|
else
|
508
498
|
return raw_value
|
509
499
|
end
|
@@ -518,7 +508,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
518
508
|
@io.seek(-4, IO::SEEK_CUR) # 1. find a padding zero,
|
519
509
|
seek_to_v2_end
|
520
510
|
break
|
521
|
-
else
|
511
|
+
else
|
522
512
|
if @version_maj == 4
|
523
513
|
size = @io.get_syncsafe
|
524
514
|
else
|
@@ -530,7 +520,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
530
520
|
end
|
531
521
|
break if @io.pos >= @tag_length # 2. reach length from header
|
532
522
|
end
|
533
|
-
end
|
523
|
+
end
|
534
524
|
|
535
525
|
### reads id3 ver 2.2.x frames and adds the contents to @tag2 hash
|
536
526
|
### NOTE: the id3v2 header does not take padding zero's into consideration
|
@@ -547,8 +537,8 @@ class ID3v2 < DelegateClass(Hash)
|
|
547
537
|
break if @io.pos >= @tag_length
|
548
538
|
end
|
549
539
|
end
|
550
|
-
end
|
551
|
-
|
540
|
+
end
|
541
|
+
|
552
542
|
### Add data to tag2["name"]
|
553
543
|
### read lang_encoding, decode data if unicode and
|
554
544
|
### create an array if the key already exists in the tag
|
@@ -558,11 +548,11 @@ class ID3v2 < DelegateClass(Hash)
|
|
558
548
|
if size > 50_000_000
|
559
549
|
raise ID3v2Error, "tag size is > 50_000_000"
|
560
550
|
end
|
561
|
-
|
551
|
+
|
562
552
|
data_io = @io.read(size)
|
563
553
|
data = decode_tag(name, data_io)
|
564
554
|
if data && !data.empty?
|
565
|
-
if self.keys.include?(name)
|
555
|
+
if self.keys.include?(name)
|
566
556
|
if self[name].is_a?(Array)
|
567
557
|
unless self[name].include?(data)
|
568
558
|
self[name] << data
|
@@ -571,7 +561,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
571
561
|
self[name] = [ self[name], data ]
|
572
562
|
end
|
573
563
|
else
|
574
|
-
self[name] = data
|
564
|
+
self[name] = data
|
575
565
|
end
|
576
566
|
|
577
567
|
if name == "TPOS" && data =~ /(\d+)\s*\/\s*(\d+)/
|
@@ -582,7 +572,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
582
572
|
|
583
573
|
puts "self[#{name.inspect}] = #{self[name].inspect}" if $DEBUG
|
584
574
|
end
|
585
|
-
|
575
|
+
|
586
576
|
### runs thru @file one char at a time looking for best guess of first MPEG
|
587
577
|
### frame, which should be first 0xff byte after id3v2 padding zero's
|
588
578
|
def seek_to_v2_end
|
@@ -591,12 +581,12 @@ class ID3v2 < DelegateClass(Hash)
|
|
591
581
|
end
|
592
582
|
@io.seek(-1, IO::SEEK_CUR)
|
593
583
|
end
|
594
|
-
|
584
|
+
|
595
585
|
### convert an 32 integer to a syncsafe string
|
596
586
|
def to_syncsafe(num)
|
597
587
|
( (num<<3) & 0x7f000000 ) + ( (num<<2) & 0x7f0000 ) + ( (num<<1) & 0x7f00 ) + ( num & 0x7f )
|
598
588
|
end
|
599
|
-
|
589
|
+
|
600
590
|
### this is especially useful for printing out APIC data because
|
601
591
|
### only the header of the APIC tag is of interest
|
602
592
|
def pretty_header(str, chars=128)
|
@@ -604,4 +594,3 @@ class ID3v2 < DelegateClass(Hash)
|
|
604
594
|
end
|
605
595
|
|
606
596
|
end
|
607
|
-
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mp3info
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillaume Pierronnet
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '3.
|
33
|
+
version: '3.15'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '3.
|
40
|
+
version: '3.15'
|
41
41
|
description: ruby-mp3info read low-level informations and manipulate tags on mp3 files.
|
42
42
|
email:
|
43
43
|
- guillaume.pierronnet@gmail.com
|
@@ -48,7 +48,6 @@ extra_rdoc_files:
|
|
48
48
|
- Manifest.txt
|
49
49
|
- README.md
|
50
50
|
files:
|
51
|
-
- ".gemtest"
|
52
51
|
- History.txt
|
53
52
|
- Manifest.txt
|
54
53
|
- README.md
|
@@ -80,9 +79,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
79
|
version: '0'
|
81
80
|
requirements: []
|
82
81
|
rubyforge_project:
|
83
|
-
rubygems_version: 2.
|
82
|
+
rubygems_version: 2.5.1
|
84
83
|
signing_key:
|
85
84
|
specification_version: 4
|
86
85
|
summary: ruby-mp3info read low-level informations and manipulate tags on mp3 files.
|
87
|
-
test_files:
|
88
|
-
- test/test_ruby-mp3info.rb
|
86
|
+
test_files: []
|
data/.gemtest
DELETED
File without changes
|