lib/mp3file/mp3_file.rb in mp3file-0.0.4 vs lib/mp3file/mp3_file.rb in mp3file-1.0.0
- old
+ new
@@ -7,11 +7,11 @@
attr_reader(:xing_header_offset, :xing_header)
attr_reader(:vbri_header_offset, :vbri_header)
attr_reader(:mpeg_version, :layer, :bitrate, :samplerate, :mode)
attr_reader(:num_frames, :total_samples, :length)
- attr_accessor(:id3v1_tag)
+ attr_accessor(:id3v1_tag, :id3v2_tag, :extra_id3v2_tags)
def initialize(file_path)
file_path = Pathname.new(file_path).expand_path if file_path.is_a?(String)
load_file(file_path)
end
@@ -71,35 +71,62 @@
@file.seek(0, IO::SEEK_END)
@file_size = @file.tell
# Try to read an ID3v1 tag.
@id3v1_tag = nil
- @file.seek(-128, IO::SEEK_END)
begin
- @id3v1_tag = ID3v1Tag.new(@file)
- rescue InvalidID3v1TagError => e
+ @file.seek(-128, IO::SEEK_END)
+ @id3v1_tag = ID3v1Tag.parse(@file)
+ rescue Mp3file::InvalidID3v1TagError
@id3v1_tag = nil
+ ensure
+ @file.seek(0, IO::SEEK_SET)
end
- @file.seek(0, IO::SEEK_SET)
# Try to detect an ID3v2 header.
- @id3v2_header = nil
+ @id3v2_tag = nil
begin
- @id3v2_header = ID3v2::Header.new(@file)
- rescue ID3v2::InvalidID3v2TagError => e
- @id3v2_header = nil
+ @id3v2_tag = ID3v2::Tag.new(@file)
+ rescue ID3v2::InvalidID3v2TagError # => e
+ # $stderr.puts "Error parsing ID3v2 tag: %s\n\t%s" %
+ # [ e.message, e.backtrace.join("\n\t") ]
+ @id3v2_tag = nil
@file.seek(0, IO::SEEK_SET)
end
# Skip past the ID3v2 header if it's present.
- if @id3v2_header
- @file.seek(@id3v2_header.tag_size + 10, IO::SEEK_SET)
+ if @id3v2_tag
+ @file.seek(@id3v2_tag.size, IO::SEEK_SET)
end
- # Try to find the first MP3 header.
- @first_header_offset, @first_header = get_next_header(@file)
+ # Some files have more than one ID3v2 tag. If we can't find an
+ # MP3 header in the next 4k, try reading another ID3v2 tag and
+ # repeat.
+ @extra_id3v2_tags = []
+ begin
+ # Try to find the first MP3 header.
+ @first_header_offset, @first_header = get_next_header(@file)
+ rescue InvalidMP3FileError
+ end_of_tags = @id3v2_tag.size + @extra_id3v2_tags.map(&:last).map(&:size).reduce(:+).to_i
+ @file.seek(end_of_tags, IO::SEEK_SET)
+ tag = nil
+ begin
+ tag = ID3v2::Tag.new(@file)
+ rescue ID3v2::InvalidID3v2TagError
+ tag = nil
+ @file.seek(end_of_tags, IO::SEEK_SET)
+ end
+
+ if tag
+ @extra_id3v2_tags << [ end_of_tags, tag ]
+ retry
+ else
+ raise
+ end
+ end
+
@mpeg_version = @first_header.version
@layer = @first_header.layer
@bitrate = @first_header.bitrate / 1000
@samplerate = @first_header.samplerate
@mode = @first_header.mode
@@ -115,11 +142,11 @@
# side_bytes.
@xing_header = nil
@file.seek(@first_header.side_bytes, IO::SEEK_CUR)
begin
@xing_header = XingHeader.new(@file)
- rescue InvalidXingHeaderError => ve
+ rescue InvalidXingHeaderError
@file.seek(@first_header_offset + 4, IO::SEEK_CUR)
end
if @xing_header
@vbr = true
@@ -153,10 +180,10 @@
while header.nil?
begin
header = MP3Header.new(file)
header_offset = file.tell - 4
- rescue InvalidMP3HeaderError => e
+ rescue InvalidMP3HeaderError
header_offset += 1
if header_offset - initial_header_offset > 4096
raise InvalidMP3FileError, "Could not find a valid MP3 header in the first 4096 bytes."
else
file.seek(header_offset, IO::SEEK_SET)