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.
Major version used when writing tags
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 179 def initialize(options = {}) @options = { :lang => "ENG", :encoding => "iso-8859-1" } @options.update(options) @text_encoding_index = TEXT_ENCODINGS.index(@options[:encoding]) unless @text_encoding_index raise(ArgumentError, "bad id3v2 text encoding specified") end @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 206 def changed? @hash_orig != @hash end
gets id3v2 tag information from io object (must support seek() method)
# File lib/mp3info/id3v2.rb, line 221 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 201 def parsed? @parsed end
dump tag for writing. Version is always 2.#{WRITE_VERSION}.0.
# File lib/mp3info/id3v2.rb, line 253 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, WRITE_VERSION) #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 if RUBY_VERSION >= "1.9.0" 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 << [ WRITE_VERSION, 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
Generated with the Darkfish Rdoc Generator 2.