This class can be used to decode id3v2 tags from files, like .mp3 or .ape for example. It works like a hash, where key represents the tag name as 3 or 4 upper case letters (respectively related to 2.2 and 2.3+ tag) and value represented as array or raw value. Written version is always 2.3.
Translate V2 to V3 tags
See id3v2.4.0-structure document, at section 4.
this is the position in the file where the tag really ends
:lang: for writing comments
:encoding: one of the string of TEXT_ENCODINGS,
use of :encoding parameter is DEPRECATED. In ruby 1.8, use utf-8 encoded strings for tags. In ruby >= 1.9, strings are automatically transcoded from their originaloriginal encoding.
possible options are described above (‘options’ attribute) you can access this object like an hash, with [] and []= methods special cases are [“disc_number”] and [“disc_total”] mirroring TPOS attribute
# File lib/mp3info/id3v2.rb, line 182 def initialize(options = {}) @options = { :lang => "ENG" } if @options[:encoding] warn("use of :encoding parameter is DEPRECATED. In ruby 1.8, use utf-8 encoded strings for tags.\n" + "In ruby >= 1.9, strings are automatically transcoded from their original encoding.") end @options.update(options) @hash = {} #TAGS.keys.each { |k| @hash[k] = nil } @hash_orig = {} super(@hash) @parsed = false @version_maj = @version_min = nil end
does this tag has been changed ?
# File lib/mp3info/id3v2.rb, line 205 def changed? @hash_orig != @hash end
gets id3v2 tag information from io object (must support seek() method)
# File lib/mp3info/id3v2.rb, line 220 def from_io(io) @io = io original_pos = @io.pos @io.extend(Mp3Info::Mp3FileMethods) version_maj, version_min, flags = @io.read(3).unpack("CCB4") @unsync, ext_header, experimental, footer = (0..3).collect { |i| flags[i].chr == '1' } raise(ID3v2Error, "can't find version_maj ('#{version_maj}')") unless [2, 3, 4].include?(version_maj) @version_maj, @version_min = version_maj, version_min @tag_length = @io.get_syncsafe @parsed = true begin case @version_maj when 2 read_id3v2_2_frames when 3, 4 # seek past extended header if present @io.seek(@io.get_syncsafe - 4, IO::SEEK_CUR) if ext_header read_id3v2_3_frames end rescue ID3v2Error => e warn("warning: id3v2 tag not fully parsed: #{e.message}") end @io_position = @io.pos @tag_length = @io_position - original_pos @hash_orig = @hash.dup #no more reading @io = nil end
does this tag has been correctly read ?
# File lib/mp3info/id3v2.rb, line 200 def parsed? @parsed end
dump tag for writing. Version is always 2.3.0
# File lib/mp3info/id3v2.rb, line 252 def to_bin #TODO handle of @tag2[TLEN"] #TODO add of crc #TODO add restrictions tag tag = "" @hash.each do |k, v| next unless v next if v.respond_to?("empty?") and v.empty? # Automagically translate V2 to V3 tags k = TAG_MAPPING_2_2_to_2_3[k] if TAG_MAPPING_2_2_to_2_3.has_key?(k) # doesn't encode id3v2.2 tags, which have 3 characters next if k.size != 4 # Output one flag for each array element, or one only if it's not an array [v].flatten.each do |value| data = encode_tag(k, value.to_s) #data << "\x00"*2 #End of tag tag << k[0,4] #4 characte max for a tag's key #tag << to_syncsafe(data.size) #+1 because of the language encoding byte size = data.size unless RUBY_1_8 size = data.dup.force_encoding("binary").size end tag << [size].pack("N") #+1 because of the language encoding byte tag << "\x00"*2 #flags tag << data end end tag_str = "ID3" #version_maj, version_min, unsync, ext_header, experimental, footer tag_str << [ 3, 0, "0000" ].pack("CCB4") tag_str << [to_syncsafe(tag.size)].pack("N") tag_str << tag puts "tag in binary format: #{tag_str.inspect}" if $DEBUG tag_str end
full version of this tag (like “2.3.0”) or nil if tag was not correctly read
# File lib/mp3info/id3v2.rb, line 211 def version if @version_maj && @version_min "2.#{@version_maj}.#{@version_min}" else nil end end