Class: ID3v2
- Inherits:
-
Hash
- Object
- Hash
- ID3v2
- Includes:
- Mp3Info::HashKeys
- Defined in:
- lib/mp3info/id3v2.rb
Overview
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.
Constant Summary collapse
- WRITE_VERSION =
Major version used when writing tags
3
- TAGS =
{ "AENC" => "Audio encryption", "APIC" => "Attached picture", "COMM" => "Comments", "COMR" => "Commercial frame", "ENCR" => "Encryption method registration", "EQUA" => "Equalization", "ETCO" => "Event timing codes", "GEOB" => "General encapsulated object", "GRID" => "Group identification registration", "IPLS" => "Involved people list", "LINK" => "Linked information", "MCDI" => "Music CD identifier", "MLLT" => "MPEG location lookup table", "OWNE" => "Ownership frame", "PRIV" => "Private frame", "PCNT" => "Play counter", "POPM" => "Popularimeter", "POSS" => "Position synchronisation frame", "RBUF" => "Recommended buffer size", "RVAD" => "Relative volume adjustment", "RVRB" => "Reverb", "SYLT" => "Synchronized lyric/text", "SYTC" => "Synchronized tempo codes", "TALB" => "Album/Movie/Show title", "TBPM" => "BPM (beats per minute)", "TCOM" => "Composer", "TCON" => "Content type", "TCOP" => "Copyright message", "TDAT" => "Date", "TDLY" => "Playlist delay", "TENC" => "Encoded by", "TEXT" => "Lyricist/Text writer", "TFLT" => "File type", "TIME" => "Time", "TIT1" => "Content group description", "TIT2" => "Title/songname/content description", "TIT3" => "Subtitle/Description refinement", "TKEY" => "Initial key", "TLAN" => "Language(s)", "TLEN" => "Length", "TMED" => "Media type", "TOAL" => "Original album/movie/show title", "TOFN" => "Original filename", "TOLY" => "Original lyricist(s)/text writer(s)", "TOPE" => "Original artist(s)/performer(s)", "TORY" => "Original release year", "TOWN" => "File owner/licensee", "TPE1" => "Lead performer(s)/Soloist(s)", "TPE2" => "Band/orchestra/accompaniment", "TPE3" => "Conductor/performer refinement", "TPE4" => "Interpreted, remixed, or otherwise modified by", "TPOS" => "Part of a set", "TPUB" => "Publisher", "TRCK" => "Track number/Position in set", "TRDA" => "Recording dates", "TRSN" => "Internet radio station name", "TRSO" => "Internet radio station owner", "TSIZ" => "Size", "TSRC" => "ISRC (international standard recording code)", "TSSE" => "Software/Hardware and settings used for encoding", "TYER" => "Year", "TXXX" => "User defined text information frame", "UFID" => "Unique file identifier", "USER" => "Terms of use", "USLT" => "Unsychronized lyric/text transcription", "WCOM" => "Commercial information", "WCOP" => "Copyright/Legal information", "WOAF" => "Official audio file webpage", "WOAR" => "Official artist/performer webpage", "WOAS" => "Official audio source webpage", "WORS" => "Official internet radio station homepage", "WPAY" => "Payment", "WPUB" => "Publishers official webpage", "WXXX" => "User defined URL link frame" }
- TAG_MAPPING_2_2_to_2_3 =
Translate V2 to V3 tags
{ "BUF" => "RBUF", "COM" => "COMM", "CRA" => "AENC", "EQU" => "EQUA", "ETC" => "ETCO", "GEO" => "GEOB", "MCI" => "MCDI", "MLL" => "MLLT", "PIC" => "APIC", "POP" => "POPM", "REV" => "RVRB", "RVA" => "RVAD", "SLT" => "SYLT", "STC" => "SYTC", "TAL" => "TALB", "TBP" => "TBPM", "TCM" => "TCOM", "TCO" => "TCON", "TCR" => "TCOP", "TDA" => "TDAT", "TDY" => "TDLY", "TEN" => "TENC", "TFT" => "TFLT", "TIM" => "TIME", "TKE" => "TKEY", "TLA" => "TLAN", "TLE" => "TLEN", "TMT" => "TMED", "TOA" => "TOPE", "TOF" => "TOFN", "TOL" => "TOLY", "TOR" => "TORY", "TOT" => "TOAL", "TP1" => "TPE1", "TP2" => "TPE2", "TP3" => "TPE3", "TP4" => "TPE4", "TPA" => "TPOS", "TPB" => "TPUB", "TRC" => "TSRC", "TRD" => "TRDA", "TRK" => "TRCK", "TSI" => "TSIZ", "TSS" => "TSSE", "TT1" => "TIT1", "TT2" => "TIT2", "TT3" => "TIT3", "TXT" => "TEXT", "TXX" => "TXXX", "TYE" => "TYER", "UFI" => "UFID", "ULT" => "USLT", "WAF" => "WOAF", "WAR" => "WOAR", "WAS" => "WOAS", "WCM" => "WCOM", "WCP" => "WCOP", "WPB" => "WPB", "WXX" => "WXXX", }
- TEXT_ENCODINGS =
See id3v2.4.0-structure document, at section 4.
["iso-8859-1", "utf-16", "utf-16be", "utf-8"]
Instance Attribute Summary collapse
-
#io_position ⇒ Object
readonly
this is the position in the file where the tag really ends.
-
#options ⇒ Object
readonly
:
lang
: for writing comments.
Instance Method Summary collapse
-
#changed? ⇒ Boolean
does this tag has been changed ?.
-
#from_io(io) ⇒ Object
gets id3v2 tag information from io object (must support #seek() method).
-
#initialize(options = {}) ⇒ ID3v2
constructor
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.
-
#parsed? ⇒ Boolean
does this tag has been correctly read ?.
-
#to_bin ⇒ Object
dump tag for writing.
-
#version ⇒ Object
full version of this tag (like “2.3.0”) or nil if tag was not correctly read.
Methods included from Mp3Info::HashKeys
Constructor Details
#initialize(options = {}) ⇒ ID3v2
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
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/mp3info/id3v2.rb', line 180 def initialize( = {}) @options = { :lang => "ENG", :encoding => "iso-8859-1" } @options.update() @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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Mp3Info::HashKeys
Instance Attribute Details
#io_position ⇒ Object (readonly)
this is the position in the file where the tag really ends
168 169 170 |
# File 'lib/mp3info/id3v2.rb', line 168 def io_position @io_position end |
#options ⇒ Object (readonly)
:lang
: for writing comments
:encoding
: one of the string of TEXT_ENCODINGS
, used as a source and destination encoding respectively for read and write tag2 values.
175 176 177 |
# File 'lib/mp3info/id3v2.rb', line 175 def @options end |
Instance Method Details
#changed? ⇒ Boolean
does this tag has been changed ?
207 208 209 |
# File 'lib/mp3info/id3v2.rb', line 207 def changed? @hash_orig != @hash end |
#from_io(io) ⇒ Object
gets id3v2 tag information from io object (must support #seek() method)
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/mp3info/id3v2.rb', line 222 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, = (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.}") end @io_position = @io.pos @tag_length = @io_position - original_pos @hash_orig = @hash.dup #no more reading @io = nil end |
#parsed? ⇒ Boolean
does this tag has been correctly read ?
202 203 204 |
# File 'lib/mp3info/id3v2.rb', line 202 def parsed? @parsed end |
#to_bin ⇒ Object
dump tag for writing. Version is always 2.#WRITE_VERSION.0.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/mp3info/id3v2.rb', line 254 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 |
#version ⇒ Object
full version of this tag (like “2.3.0”) or nil if tag was not correctly read
213 214 215 216 217 218 219 |
# File 'lib/mp3info/id3v2.rb', line 213 def version if @version_maj && @version_min "2.#{@version_maj}.#{@version_min}" else nil end end |