ruby-mp3info 0.6.13 → 0.6.14
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +9 -0
- data/Manifest.txt +1 -1
- data/{README.txt → README.rdoc} +1 -1
- data/Rakefile +6 -2
- data/lib/mp3info.rb +99 -95
- data/lib/mp3info/extension_modules.rb +6 -1
- data/lib/mp3info/id3v2.rb +8 -2
- data/test/test_ruby-mp3info.rb +10 -0
- metadata +91 -18
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 0.6.14 / 2011-06-17
|
2
|
+
|
3
|
+
* Added a check for nil that was seen causing problems when processing files. (thanks to Carl Hall)
|
4
|
+
* Fixed reading on win32, requires binary flag. (thanks to Jonas Tingeborn)
|
5
|
+
* Fixed white spaces. Replaced tabs with spaces to make the source readable on for users other than the original author. (thanks to Jonas Tingeborn)
|
6
|
+
* Add :parse_mp3 flag to new/open. (thanks to Dave Lee)
|
7
|
+
* Add benchmark for parsing performance. (thanks to Dave Lee)
|
8
|
+
* fixed ID3v2#io_position computing, so Mp3Info#audio_content() is correct now
|
9
|
+
|
1
10
|
=== 0.6.13 / 2009-05-26
|
2
11
|
|
3
12
|
* fixed bad mapping of artist inside id3 2.2
|
data/Manifest.txt
CHANGED
data/{README.txt → README.rdoc}
RENAMED
@@ -3,7 +3,7 @@ ruby-mp3info
|
|
3
3
|
by Guillaume Pierronnet
|
4
4
|
* http://ruby-mp3info.rubyforge.org/
|
5
5
|
* http://rubyforge.org/projects/ruby-mp3info/
|
6
|
-
*
|
6
|
+
* https://github.com/moumar/ruby-mp3info
|
7
7
|
|
8
8
|
== DESCRIPTION:
|
9
9
|
|
data/Rakefile
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
|
+
|
6
|
+
Hoe.plugin :yard
|
7
|
+
|
5
8
|
$:.unshift("./lib/")
|
6
9
|
require 'mp3info'
|
7
10
|
|
@@ -10,10 +13,11 @@ Hoe.new('ruby-mp3info', Mp3Info::VERSION) do |p|
|
|
10
13
|
p.author = "Guillaume Pierronnet"
|
11
14
|
p.email = "moumar@rubyforge.org"
|
12
15
|
p.summary = "ruby-mp3info is a pure-ruby library to retrieve low level informations on mp3 files and manipulate id3v1 and id3v2 tags"
|
13
|
-
p.description = p.paragraphs_of('README.
|
14
|
-
p.url = p.paragraphs_of('README.
|
16
|
+
p.description = p.paragraphs_of('README.rdoc', 5..9).join("\n\n")
|
17
|
+
p.url = p.paragraphs_of('README.rdoc', 0).first.split(/\n/)[1..-1]
|
15
18
|
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
19
|
p.remote_rdoc_dir = ''
|
20
|
+
p.rdoc_locations << "rubyforge.org:/var/www/gforge-projects/ruby-mp3info/"
|
17
21
|
end
|
18
22
|
|
19
23
|
# vim: syntax=Ruby
|
data/lib/mp3info.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# coding:utf-8
|
2
|
-
# $Id: mp3info.rb 98 2008-09-16 11:07:31Z moumar $
|
3
2
|
# License:: Ruby
|
4
3
|
# Author:: Guillaume Pierronnet (mailto:moumar_AT__rubyforge_DOT_org)
|
5
4
|
# Website:: http://ruby-mp3info.rubyforge.org/
|
@@ -18,7 +17,7 @@ end
|
|
18
17
|
|
19
18
|
class Mp3Info
|
20
19
|
|
21
|
-
VERSION = "0.6.
|
20
|
+
VERSION = "0.6.14"
|
22
21
|
|
23
22
|
LAYER = [ nil, 3, 2, 1]
|
24
23
|
BITRATE = {
|
@@ -161,7 +160,7 @@ class Mp3Info
|
|
161
160
|
|
162
161
|
# Test the presence of an id3v1 tag in file +filename+
|
163
162
|
def self.hastag1?(filename)
|
164
|
-
File.open(filename) { |f|
|
163
|
+
File.open(filename,"rb") { |f|
|
165
164
|
f.seek(-TAG1_SIZE, File::SEEK_END)
|
166
165
|
f.read(3) == "TAG"
|
167
166
|
}
|
@@ -169,7 +168,7 @@ class Mp3Info
|
|
169
168
|
|
170
169
|
# Test the presence of an id3v2 tag in file +filename+
|
171
170
|
def self.hastag2?(filename)
|
172
|
-
File.open(filename) { |f|
|
171
|
+
File.open(filename,"rb") { |f|
|
173
172
|
f.read(3) == "ID3"
|
174
173
|
}
|
175
174
|
end
|
@@ -191,15 +190,15 @@ class Mp3Info
|
|
191
190
|
|
192
191
|
# Instantiate Mp3Info object with name +filename+.
|
193
192
|
# options hash is used for ID3v2#new.
|
194
|
-
#
|
193
|
+
# Specify :parse_tags => false to disable the processing
|
195
194
|
# of the tags (read and write).
|
195
|
+
# Specify :parse_mp3 => false to disable processing of the mp3
|
196
196
|
def initialize(filename, options = {})
|
197
197
|
warn("#{self.class}::new() does not take block; use #{self.class}::open() instead") if block_given?
|
198
198
|
@filename = filename
|
199
|
+
options = {:parse_mp3 => true, :parse_tags => true}.update(options)
|
199
200
|
@tag_parsing_enabled = options.delete(:parse_tags)
|
200
|
-
|
201
|
-
@tag_parsing_enabled = true
|
202
|
-
end
|
201
|
+
@mp3_parsing_enabled = options.delete(:parse_mp3)
|
203
202
|
@id3v2_options = options
|
204
203
|
reload
|
205
204
|
end
|
@@ -249,74 +248,10 @@ class Mp3Info
|
|
249
248
|
@tag_orig = @tag.dup
|
250
249
|
end
|
251
250
|
|
252
|
-
|
253
|
-
|
254
|
-
### head (fixnum) = valid 4 byte MPEG header
|
255
|
-
|
256
|
-
found = false
|
257
|
-
|
258
|
-
head = nil
|
259
|
-
5.times do
|
260
|
-
head = find_next_frame()
|
261
|
-
@first_frame_pos = @file.pos - 4
|
262
|
-
current_frame = Mp3Info.get_frames_infos(head)
|
263
|
-
@mpeg_version = current_frame[:mpeg_version]
|
264
|
-
@layer = current_frame[:layer]
|
265
|
-
@header[:error_protection] = head[16] == 0 ? true : false
|
266
|
-
@bitrate = current_frame[:bitrate]
|
267
|
-
@samplerate = current_frame[:samplerate]
|
268
|
-
@header[:padding] = current_frame[:padding]
|
269
|
-
@header[:private] = head[8] == 0 ? true : false
|
270
|
-
@channel_mode = CHANNEL_MODE[@channel_num = Mp3Info.bits(head, 7,6)]
|
271
|
-
@header[:mode_extension] = Mp3Info.bits(head, 5,4)
|
272
|
-
@header[:copyright] = (head[3] == 1 ? true : false)
|
273
|
-
@header[:original] = (head[2] == 1 ? true : false)
|
274
|
-
@header[:emphasis] = Mp3Info.bits(head, 1,0)
|
275
|
-
@vbr = false
|
276
|
-
found = true
|
277
|
-
break
|
251
|
+
if @mp3_parsing_enabled
|
252
|
+
parse_mp3
|
278
253
|
end
|
279
254
|
|
280
|
-
raise(Mp3InfoError, "Cannot find good frame") unless found
|
281
|
-
|
282
|
-
seek = @mpeg_version == 1 ?
|
283
|
-
(@channel_num == 3 ? 17 : 32) :
|
284
|
-
(@channel_num == 3 ? 9 : 17)
|
285
|
-
|
286
|
-
@file.seek(seek, IO::SEEK_CUR)
|
287
|
-
|
288
|
-
vbr_head = @file.read(4)
|
289
|
-
if vbr_head == "Xing"
|
290
|
-
puts "Xing header (VBR) detected" if $DEBUG
|
291
|
-
flags = @file.get32bits
|
292
|
-
stream_size = frame_count = 0
|
293
|
-
flags[1] == 1 and frame_count = @file.get32bits
|
294
|
-
flags[2] == 1 and stream_size = @file.get32bits
|
295
|
-
puts "#{frame_count} frames" if $DEBUG
|
296
|
-
raise(Mp3InfoError, "bad VBR header") if frame_count.zero?
|
297
|
-
# currently this just skips the TOC entries if they're found
|
298
|
-
@file.seek(100, IO::SEEK_CUR) if flags[0] == 1
|
299
|
-
#@vbr_quality = @file.get32bits if flags[3] == 1
|
300
|
-
|
301
|
-
samples_per_frame = SAMPLES_PER_FRAME[@layer][@mpeg_version]
|
302
|
-
@length = frame_count * samples_per_frame / Float(@samplerate)
|
303
|
-
|
304
|
-
@bitrate = (((stream_size/frame_count)*@samplerate)/144) / 1024
|
305
|
-
@vbr = true
|
306
|
-
else
|
307
|
-
# for cbr, calculate duration with the given bitrate
|
308
|
-
stream_size = @file.stat.size - (hastag1? ? TAG1_SIZE : 0) - (@tag2.io_position || 0)
|
309
|
-
@length = ((stream_size << 3)/1000.0)/@bitrate
|
310
|
-
# read the first 100 frames and decide if the mp3 is vbr and needs full scan
|
311
|
-
begin
|
312
|
-
bitrate, length = frame_scan(100)
|
313
|
-
if @bitrate != bitrate
|
314
|
-
@vbr = true
|
315
|
-
@bitrate, @length = frame_scan
|
316
|
-
end
|
317
|
-
rescue Mp3InfoInternalError
|
318
|
-
end
|
319
|
-
end
|
320
255
|
ensure
|
321
256
|
@file.close
|
322
257
|
end
|
@@ -403,9 +338,9 @@ class Mp3Info
|
|
403
338
|
|
404
339
|
# @tag1 has precedence over @tag
|
405
340
|
if @tag1 == @tag1_orig
|
406
|
-
|
407
|
-
|
408
|
-
|
341
|
+
@tag.each do |k, v|
|
342
|
+
@tag1[k] = v
|
343
|
+
end
|
409
344
|
end
|
410
345
|
|
411
346
|
# ruby-mp3info can only write v2.3 tags
|
@@ -452,28 +387,28 @@ class Mp3Info
|
|
452
387
|
raise(Mp3InfoError, "file is not writable") unless File.writable?(@filename)
|
453
388
|
tempfile_name = nil
|
454
389
|
File.open(@filename, 'rb+') do |file|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
390
|
+
#if tag2 already exists, seek to end of it
|
391
|
+
if @tag2.parsed?
|
392
|
+
file.seek(@tag2.io_position)
|
393
|
+
end
|
459
394
|
# if @file.read(3) == "ID3"
|
460
395
|
# version_maj, version_min, flags = @file.read(3).unpack("CCB4")
|
461
396
|
# unsync, ext_header, experimental, footer = (0..3).collect { |i| flags[i].chr == '1' }
|
462
|
-
#
|
397
|
+
# tag2_len = @file.get_syncsafe
|
463
398
|
# @file.seek(@file.get_syncsafe - 4, IO::SEEK_CUR) if ext_header
|
464
|
-
#
|
399
|
+
# @file.seek(tag2_len, IO::SEEK_CUR)
|
465
400
|
# end
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
401
|
+
tempfile_name = @filename + ".tmp"
|
402
|
+
File.open(tempfile_name, "wb") do |tempfile|
|
403
|
+
unless @tag2.empty?
|
404
|
+
tempfile.write(@tag2.to_bin)
|
405
|
+
end
|
406
|
+
|
407
|
+
bufsiz = file.stat.blksize || 4096
|
408
|
+
while buf = file.read(bufsiz)
|
409
|
+
tempfile.write(buf)
|
410
|
+
end
|
411
|
+
end
|
477
412
|
end
|
478
413
|
File.rename(tempfile_name, @filename)
|
479
414
|
end
|
@@ -499,7 +434,7 @@ class Mp3Info
|
|
499
434
|
# counter, or whatever you like ;) +frame+ is a hash with the following keys:
|
500
435
|
# :layer, :bitrate, :samplerate, :mpeg_version, :padding and :size (in bytes)
|
501
436
|
def each_frame
|
502
|
-
File.open(@filename, '
|
437
|
+
File.open(@filename, 'rb') do |file|
|
503
438
|
file.seek(@first_frame_pos, File::SEEK_SET)
|
504
439
|
loop do
|
505
440
|
head = file.read(4).unpack("N").first
|
@@ -639,6 +574,75 @@ private
|
|
639
574
|
[average_bitrate, length]
|
640
575
|
end
|
641
576
|
|
577
|
+
def parse_mp3
|
578
|
+
### extracts MPEG info from MPEG header and stores it in the hash @mpeg
|
579
|
+
### head (fixnum) = valid 4 byte MPEG header
|
580
|
+
|
581
|
+
found = false
|
582
|
+
|
583
|
+
head = nil
|
584
|
+
5.times do
|
585
|
+
head = find_next_frame()
|
586
|
+
@first_frame_pos = @file.pos - 4
|
587
|
+
current_frame = Mp3Info.get_frames_infos(head)
|
588
|
+
@mpeg_version = current_frame[:mpeg_version]
|
589
|
+
@layer = current_frame[:layer]
|
590
|
+
@header[:error_protection] = head[16] == 0 ? true : false
|
591
|
+
@bitrate = current_frame[:bitrate]
|
592
|
+
@samplerate = current_frame[:samplerate]
|
593
|
+
@header[:padding] = current_frame[:padding]
|
594
|
+
@header[:private] = head[8] == 0 ? true : false
|
595
|
+
@channel_mode = CHANNEL_MODE[@channel_num = Mp3Info.bits(head, 7,6)]
|
596
|
+
@header[:mode_extension] = Mp3Info.bits(head, 5,4)
|
597
|
+
@header[:copyright] = (head[3] == 1 ? true : false)
|
598
|
+
@header[:original] = (head[2] == 1 ? true : false)
|
599
|
+
@header[:emphasis] = Mp3Info.bits(head, 1,0)
|
600
|
+
@vbr = false
|
601
|
+
found = true
|
602
|
+
break
|
603
|
+
end
|
604
|
+
|
605
|
+
raise(Mp3InfoError, "Cannot find good frame") unless found
|
606
|
+
|
607
|
+
seek = @mpeg_version == 1 ?
|
608
|
+
(@channel_num == 3 ? 17 : 32) :
|
609
|
+
(@channel_num == 3 ? 9 : 17)
|
610
|
+
|
611
|
+
@file.seek(seek, IO::SEEK_CUR)
|
612
|
+
|
613
|
+
vbr_head = @file.read(4)
|
614
|
+
if vbr_head == "Xing"
|
615
|
+
puts "Xing header (VBR) detected" if $DEBUG
|
616
|
+
flags = @file.get32bits
|
617
|
+
stream_size = frame_count = 0
|
618
|
+
flags[1] == 1 and frame_count = @file.get32bits
|
619
|
+
flags[2] == 1 and stream_size = @file.get32bits
|
620
|
+
puts "#{frame_count} frames" if $DEBUG
|
621
|
+
raise(Mp3InfoError, "bad VBR header") if frame_count.zero?
|
622
|
+
# currently this just skips the TOC entries if they're found
|
623
|
+
@file.seek(100, IO::SEEK_CUR) if flags[0] == 1
|
624
|
+
#@vbr_quality = @file.get32bits if flags[3] == 1
|
625
|
+
|
626
|
+
samples_per_frame = SAMPLES_PER_FRAME[@layer][@mpeg_version]
|
627
|
+
@length = frame_count * samples_per_frame / Float(@samplerate)
|
628
|
+
|
629
|
+
@bitrate = (((stream_size/frame_count)*@samplerate)/144) / 1024
|
630
|
+
@vbr = true
|
631
|
+
else
|
632
|
+
# for cbr, calculate duration with the given bitrate
|
633
|
+
stream_size = @file.stat.size - (hastag1? ? TAG1_SIZE : 0) - (@tag2.io_position || 0)
|
634
|
+
@length = ((stream_size << 3)/1000.0)/@bitrate
|
635
|
+
# read the first 100 frames and decide if the mp3 is vbr and needs full scan
|
636
|
+
begin
|
637
|
+
bitrate, length = frame_scan(100)
|
638
|
+
if @bitrate != bitrate
|
639
|
+
@vbr = true
|
640
|
+
@bitrate, @length = frame_scan
|
641
|
+
end
|
642
|
+
rescue Mp3InfoInternalError
|
643
|
+
end
|
644
|
+
end
|
645
|
+
end
|
642
646
|
|
643
647
|
### returns the selected bit range (b, a) as a number
|
644
648
|
### NOTE: b > a if not, returns 0
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
# License:: Ruby
|
3
|
+
# Author:: Guillaume Pierronnet (mailto:moumar_AT__rubyforge_DOT_org)
|
4
|
+
# Website:: http://ruby-mp3info.rubyforge.org/
|
5
|
+
|
1
6
|
class Mp3Info
|
2
7
|
module HashKeys #:nodoc:
|
3
8
|
### lets you specify hash["key"] as hash.key
|
@@ -18,7 +23,7 @@ class Mp3Info
|
|
18
23
|
alias getbyte []
|
19
24
|
else
|
20
25
|
def getbyte(i)
|
21
|
-
self[i].ord
|
26
|
+
self[i].ord unless self[i].nil?
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
data/lib/mp3info/id3v2.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
# License:: Ruby
|
3
|
+
# Author:: Guillaume Pierronnet (mailto:moumar_AT__rubyforge_DOT_org)
|
4
|
+
# Website:: http://ruby-mp3info.rubyforge.org/
|
5
|
+
|
1
6
|
require "delegate"
|
2
7
|
require "iconv"
|
3
8
|
|
@@ -223,7 +228,6 @@ class ID3v2 < DelegateClass(Hash)
|
|
223
228
|
raise(ID3v2Error, "can't find version_maj ('#{version_maj}')") unless [2, 3, 4].include?(version_maj)
|
224
229
|
@version_maj, @version_min = version_maj, version_min
|
225
230
|
@tag_length = @io.get_syncsafe
|
226
|
-
@io_position = original_pos + @tag_length
|
227
231
|
|
228
232
|
@parsed = true
|
229
233
|
begin
|
@@ -238,6 +242,8 @@ class ID3v2 < DelegateClass(Hash)
|
|
238
242
|
rescue ID3v2Error => e
|
239
243
|
warn("warning: id3v2 tag not fully parsed: #{e.message}")
|
240
244
|
end
|
245
|
+
@io_position = @io.pos
|
246
|
+
@tag_length = @io_position - original_pos
|
241
247
|
|
242
248
|
@hash_orig = @hash.dup
|
243
249
|
#no more reading
|
@@ -339,7 +345,7 @@ class ID3v2 < DelegateClass(Hash)
|
|
339
345
|
end
|
340
346
|
end
|
341
347
|
# remove padding zeros for textual tags
|
342
|
-
out.sub!(/\0*$/, '')
|
348
|
+
out.sub!(/\0*$/, '') unless out.nil?
|
343
349
|
return out
|
344
350
|
else
|
345
351
|
return raw_value
|
data/test/test_ruby-mp3info.rb
CHANGED
@@ -441,6 +441,16 @@ class Mp3InfoTest < Test::Unit::TestCase
|
|
441
441
|
end
|
442
442
|
end
|
443
443
|
|
444
|
+
def test_audio_content_problematic
|
445
|
+
File.open(TEMP_FILE, "w") { |f| f.write(FIXTURES["audio_content_fixture"]) }
|
446
|
+
Mp3Info.open(TEMP_FILE) do |mp3|
|
447
|
+
expected_pos = 150
|
448
|
+
audio_content_pos, audio_content_size = mp3.audio_content
|
449
|
+
assert_equal expected_pos, audio_content_pos
|
450
|
+
assert_equal File.size(TEMP_FILE) - expected_pos, audio_content_size
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
444
454
|
def test_headerless_vbr_file
|
445
455
|
mp3_length = 3
|
446
456
|
# this will generate a 15 sec mp3 file (44100hz*16bit*2channels) = 60/4 = 15
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mp3info
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 6
|
9
|
+
- 14
|
10
|
+
version: 0.6.14
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Guillaume Pierronnet
|
@@ -9,20 +15,80 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date:
|
13
|
-
default_executable:
|
18
|
+
date: 2011-06-17 00:00:00 Z
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
|
-
name: hoe
|
21
|
+
name: hoe-yard
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 31
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
version: 0.1.2
|
17
34
|
type: :development
|
18
|
-
|
19
|
-
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: hoe
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
20
41
|
requirements:
|
21
42
|
- - ">="
|
22
43
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
25
|
-
|
44
|
+
hash: 47
|
45
|
+
segments:
|
46
|
+
- 2
|
47
|
+
- 8
|
48
|
+
- 0
|
49
|
+
version: 2.8.0
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
description: |-
|
53
|
+
* written in pure ruby
|
54
|
+
* read low-level informations like bitrate, length, samplerate, etc...
|
55
|
+
* read, write, remove id3v1 and id3v2 tags
|
56
|
+
* correctly read VBR files (with or without Xing header)
|
57
|
+
* only 2.3 version is supported for writings id3v2 tags
|
58
|
+
|
59
|
+
== SYNOPSIS:
|
60
|
+
|
61
|
+
a good exercise is to read the test.rb to understand how the library works deeper
|
62
|
+
|
63
|
+
require "mp3info"
|
64
|
+
# read and display infos & tags
|
65
|
+
Mp3Info.open("myfile.mp3") do |mp3info|
|
66
|
+
puts mp3info
|
67
|
+
end
|
68
|
+
|
69
|
+
# read/write tag1 and tag2 with Mp3Info#tag attribute
|
70
|
+
# when reading tag2 have priority over tag1
|
71
|
+
# when writing, each tag is written.
|
72
|
+
Mp3Info.open("myfile.mp3") do |mp3|
|
73
|
+
puts mp3.tag.title
|
74
|
+
puts mp3.tag.artist
|
75
|
+
puts mp3.tag.album
|
76
|
+
puts mp3.tag.tracknum
|
77
|
+
mp3.tag.title = "track title"
|
78
|
+
mp3.tag.artist = "artist name"
|
79
|
+
end
|
80
|
+
|
81
|
+
Mp3Info.open("myfile.mp3") do |mp3|
|
82
|
+
# you can access four letter v2 tags like this
|
83
|
+
puts mp3.tag2.TIT2
|
84
|
+
mp3.tag2.TIT2 = "new TIT2"
|
85
|
+
# or like that
|
86
|
+
mp3.tag2["TIT2"]
|
87
|
+
# at this time, only COMM tag is processed after reading and before writing
|
88
|
+
# according to ID3v2#options hash
|
89
|
+
mp3.tag2.options[:lang] = "FRE"
|
90
|
+
mp3.tag2.COMM = "my comment in french, correctly handled when reading and writing"
|
91
|
+
end
|
26
92
|
email: moumar@rubyforge.org
|
27
93
|
executables: []
|
28
94
|
|
@@ -31,43 +97,50 @@ extensions: []
|
|
31
97
|
extra_rdoc_files:
|
32
98
|
- History.txt
|
33
99
|
- Manifest.txt
|
34
|
-
- README.txt
|
35
100
|
files:
|
36
101
|
- History.txt
|
37
102
|
- Manifest.txt
|
38
|
-
- README.
|
103
|
+
- README.rdoc
|
39
104
|
- Rakefile
|
40
105
|
- install.rb
|
41
106
|
- lib/mp3info.rb
|
42
107
|
- lib/mp3info/extension_modules.rb
|
43
108
|
- lib/mp3info/id3v2.rb
|
44
109
|
- test/test_ruby-mp3info.rb
|
45
|
-
has_rdoc: true
|
46
110
|
homepage:
|
111
|
+
licenses: []
|
112
|
+
|
47
113
|
post_install_message:
|
48
114
|
rdoc_options:
|
49
|
-
- --
|
50
|
-
-
|
115
|
+
- --title
|
116
|
+
- RubyMp3info Documentation
|
117
|
+
- --quiet
|
51
118
|
require_paths:
|
52
119
|
- lib
|
53
120
|
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
54
122
|
requirements:
|
55
123
|
- - ">="
|
56
124
|
- !ruby/object:Gem::Version
|
125
|
+
hash: 3
|
126
|
+
segments:
|
127
|
+
- 0
|
57
128
|
version: "0"
|
58
|
-
version:
|
59
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
60
131
|
requirements:
|
61
132
|
- - ">="
|
62
133
|
- !ruby/object:Gem::Version
|
134
|
+
hash: 3
|
135
|
+
segments:
|
136
|
+
- 0
|
63
137
|
version: "0"
|
64
|
-
version:
|
65
138
|
requirements: []
|
66
139
|
|
67
140
|
rubyforge_project: ruby-mp3info
|
68
|
-
rubygems_version: 1.
|
141
|
+
rubygems_version: 1.8.5
|
69
142
|
signing_key:
|
70
|
-
specification_version:
|
143
|
+
specification_version: 3
|
71
144
|
summary: ruby-mp3info is a pure-ruby library to retrieve low level informations on mp3 files and manipulate id3v1 and id3v2 tags
|
72
145
|
test_files:
|
73
146
|
- test/test_ruby-mp3info.rb
|