ruby-mp3info 0.8.9 → 0.8.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|