Module: ID3
- Defined in:
- lib/id3.rb
Overview
Defined Under Namespace
Classes: AudioFile, Frame, GenericTag, RestrictedOrderedHash, Tag1, Tag2
Constant Summary collapse
- ID3v1tagSize =
ID3v1 and ID3v1.1 have fixed size tags
128
- ID3v1versionbyte =
125
- ID3v2headerSize =
10
- SUPPORTED_SYMBOLS =
{ "1.0" => {"ARTIST"=>33..62 , "ALBUM"=>63..92 ,"TITLE"=>3..32, "YEAR"=>93..96 , "COMMENT"=>97..126,"GENREID"=>127, # "VERSION"=>"1.0" } , "1.1" => {"ARTIST"=>33..62 , "ALBUM"=>63..92 ,"TITLE"=>3..32, "YEAR"=>93..96 , "COMMENT"=>97..124, "TRACKNUM"=>126, "GENREID"=>127, # "VERSION"=>"1.1" } , "2.2.0" => {"CONTENTGROUP"=>"TT1", "TITLE"=>"TT2", "SUBTITLE"=>"TT3", "ARTIST"=>"TP1", "BAND"=>"TP2", "CONDUCTOR"=>"TP3", "MIXARTIST"=>"TP4", "COMPOSER"=>"TCM", "LYRICIST"=>"TXT", "LANGUAGE"=>"TLA", "CONTENTTYPE"=>"TCO", "ALBUM"=>"TAL", "TRACKNUM"=>"TRK", "PARTINSET"=>"TPA", "ISRC"=>"TRC", "DATE"=>"TDA", "YEAR"=>"TYE", "TIME"=>"TIM", "RECORDINGDATES"=>"TRD", "ORIGYEAR"=>"TOR", "BPM"=>"TBP", "MEDIATYPE"=>"TMT", "FILETYPE"=>"TFT", "COPYRIGHT"=>"TCR", "PUBLISHER"=>"TPB", "ENCODEDBY"=>"TEN", "ENCODERSETTINGS"=>"TSS", "SONGLEN"=>"TLE", "SIZE"=>"TSI", "PLAYLISTDELAY"=>"TDY", "INITIALKEY"=>"TKE", "ORIGALBUM"=>"TOT", "ORIGFILENAME"=>"TOF", "ORIGARTIST"=>"TOA", "ORIGLYRICIST"=>"TOL", "USERTEXT"=>"TXX", "WWWAUDIOFILE"=>"WAF", "WWWARTIST"=>"WAR", "WWWAUDIOSOURCE"=>"WAS", "WWWCOMMERCIALINFO"=>"WCM", "WWWCOPYRIGHT"=>"WCP", "WWWPUBLISHER"=>"WPB", "WWWUSER"=>"WXX", "UNIQUEFILEID"=>"UFI", "INVOLVEDPEOPLE"=>"IPL", "UNSYNCEDLYRICS"=>"ULT", "COMMENT"=>"COM", "CDID"=>"MCI", "EVENTTIMING"=>"ETC", "MPEGLOOKUP"=>"MLL", "SYNCEDTEMPO"=>"STC", "SYNCEDLYRICS"=>"SLT", "VOLUMEADJ"=>"RVA", "EQUALIZATION"=>"EQU", "REVERB"=>"REV", "PICTURE"=>"PIC", "GENERALOBJECT"=>"GEO", "PLAYCOUNTER"=>"CNT", "POPULARIMETER"=>"POP", "BUFFERSIZE"=>"BUF", "CRYPTEDMETA"=>"CRM", "AUDIOCRYPTO"=>"CRA", "LINKED"=>"LNK" } , "2.3.0" => {"CONTENTGROUP"=>"TIT1", "TITLE"=>"TIT2", "SUBTITLE"=>"TIT3", "ARTIST"=>"TPE1", "BAND"=>"TPE2", "CONDUCTOR"=>"TPE3", "MIXARTIST"=>"TPE4", "COMPOSER"=>"TCOM", "LYRICIST"=>"TEXT", "LANGUAGE"=>"TLAN", "CONTENTTYPE"=>"TCON", "ALBUM"=>"TALB", "TRACKNUM"=>"TRCK", "PARTINSET"=>"TPOS", "ISRC"=>"TSRC", "DATE"=>"TDAT", "YEAR"=>"TYER", "TIME"=>"TIME", "RECORDINGDATES"=>"TRDA", "ORIGYEAR"=>"TORY", "SIZE"=>"TSIZ", "BPM"=>"TBPM", "MEDIATYPE"=>"TMED", "FILETYPE"=>"TFLT", "COPYRIGHT"=>"TCOP", "PUBLISHER"=>"TPUB", "ENCODEDBY"=>"TENC", "ENCODERSETTINGS"=>"TSSE", "SONGLEN"=>"TLEN", "PLAYLISTDELAY"=>"TDLY", "INITIALKEY"=>"TKEY", "ORIGALBUM"=>"TOAL", "ORIGFILENAME"=>"TOFN", "ORIGARTIST"=>"TOPE", "ORIGLYRICIST"=>"TOLY", "FILEOWNER"=>"TOWN", "NETRADIOSTATION"=>"TRSN", "NETRADIOOWNER"=>"TRSO", "USERTEXT"=>"TXXX", "WWWAUDIOFILE"=>"WOAF", "WWWARTIST"=>"WOAR", "WWWAUDIOSOURCE"=>"WOAS", "WWWCOMMERCIALINFO"=>"WCOM", "WWWCOPYRIGHT"=>"WCOP", "WWWPUBLISHER"=>"WPUB", "WWWRADIOPAGE"=>"WORS", "WWWPAYMENT"=>"WPAY", "WWWUSER"=>"WXXX", "UNIQUEFILEID"=>"UFID", "INVOLVEDPEOPLE"=>"IPLS", "UNSYNCEDLYRICS"=>"USLT", "COMMENT"=>"COMM", "TERMSOFUSE"=>"USER", "CDID"=>"MCDI", "EVENTTIMING"=>"ETCO", "MPEGLOOKUP"=>"MLLT", "SYNCEDTEMPO"=>"SYTC", "SYNCEDLYRICS"=>"SYLT", "VOLUMEADJ"=>"RVAD", "EQUALIZATION"=>"EQUA", "REVERB"=>"RVRB", "PICTURE"=>"APIC", "GENERALOBJECT"=>"GEOB", "PLAYCOUNTER"=>"PCNT", "POPULARIMETER"=>"POPM", "BUFFERSIZE"=>"RBUF", "AUDIOCRYPTO"=>"AENC", "LINKEDINFO"=>"LINK", "POSITIONSYNC"=>"POSS", "COMMERCIAL"=>"COMR", "CRYPTOREG"=>"ENCR", "GROUPINGREG"=>"GRID", "PRIVATE"=>"PRIV" } , "2.4.0" => {"CONTENTGROUP"=>"TIT1", "TITLE"=>"TIT2", "SUBTITLE"=>"TIT3", "ARTIST"=>"TPE1", "BAND"=>"TPE2", "CONDUCTOR"=>"TPE3", "MIXARTIST"=>"TPE4", "COMPOSER"=>"TCOM", "LYRICIST"=>"TEXT", "LANGUAGE"=>"TLAN", "CONTENTTYPE"=>"TCON", "ALBUM"=>"TALB", "TRACKNUM"=>"TRCK", "PARTINSET"=>"TPOS", "ISRC"=>"TSRC", "RECORDINGTIME"=>"TDRC", "ORIGRELEASETIME"=>"TDOR", "BPM"=>"TBPM", "MEDIATYPE"=>"TMED", "FILETYPE"=>"TFLT", "COPYRIGHT"=>"TCOP", "PUBLISHER"=>"TPUB", "ENCODEDBY"=>"TENC", "ENCODERSETTINGS"=>"TSSE", "SONGLEN"=>"TLEN", "PLAYLISTDELAY"=>"TDLY", "INITIALKEY"=>"TKEY", "ORIGALBUM"=>"TOAL", "ORIGFILENAME"=>"TOFN", "ORIGARTIST"=>"TOPE", "ORIGLYRICIST"=>"TOLY", "FILEOWNER"=>"TOWN", "NETRADIOSTATION"=>"TRSN", "NETRADIOOWNER"=>"TRSO", "USERTEXT"=>"TXXX", "SETSUBTITLE"=>"TSST", "MOOD"=>"TMOO", "PRODUCEDNOTICE"=>"TPRO", "ENCODINGTIME"=>"TDEN", "RELEASETIME"=>"TDRL", "TAGGINGTIME"=>"TDTG", "ALBUMSORTORDER"=>"TSOA", "PERFORMERSORTORDER"=>"TSOP", "TITLESORTORDER"=>"TSOT", "WWWAUDIOFILE"=>"WOAF", "WWWARTIST"=>"WOAR", "WWWAUDIOSOURCE"=>"WOAS", "WWWCOMMERCIALINFO"=>"WCOM", "WWWCOPYRIGHT"=>"WCOP", "WWWPUBLISHER"=>"WPUB", "WWWRADIOPAGE"=>"WORS", "WWWPAYMENT"=>"WPAY", "WWWUSER"=>"WXXX", "UNIQUEFILEID"=>"UFID", "MUSICIANCREDITLIST"=>"TMCL", "INVOLVEDPEOPLE2"=>"TIPL", "UNSYNCEDLYRICS"=>"USLT", "COMMENT"=>"COMM", "TERMSOFUSE"=>"USER", "CDID"=>"MCDI", "EVENTTIMING"=>"ETCO", "MPEGLOOKUP"=>"MLLT", "SYNCEDTEMPO"=>"SYTC", "SYNCEDLYRICS"=>"SYLT", "VOLUMEADJ2"=>"RVA2", "EQUALIZATION2"=>"EQU2", "REVERB"=>"RVRB", "PICTURE"=>"APIC", "GENERALOBJECT"=>"GEOB", "PLAYCOUNTER"=>"PCNT", "POPULARIMETER"=>"POPM", "BUFFERSIZE"=>"RBUF", "AUDIOCRYPTO"=>"AENC", "LINKEDINFO"=>"LINK", "POSITIONSYNC"=>"POSS", "COMMERCIAL"=>"COMR", "CRYPTOREG"=>"ENCR", "GROUPINGREG"=>"GRID", "PRIVATE"=>"PRIV", "OWNERSHIP"=>"OWNE", "SIGNATURE"=>"SIGN", "SEEKFRAME"=>"SEEK", "AUDIOSEEKPOINT"=>"ASPI" } }
- TAG_HEADER_FLAG_MASK =
Flags in the ID3-Tag Header:
{ # the mask is inverse, for error detection # those flags are supposed to be zero! "2.2.0" => 0x3F, # 0xC0 , "2.3.0" => 0x1F, # 0xE0 , "2.4.0" => 0x0F # 0xF0 }
- TAG_HEADER_FLAGS =
{ "2.2.0" => { "Unsynchronisation" => 0x80 , "Compression" => 0x40 , } , "2.3.0" => { "Unsynchronisation" => 0x80 , "ExtendedHeader" => 0x40 , "Experimental" => 0x20 , } , "2.4.0" => { "Unsynchronisation" => 0x80 , "ExtendedHeader" => 0x40 , "Experimental" => 0x20 , "Footer" => 0x10 , } }
- FRAME_HEADER_FLAG_MASK =
Flags in the ID3-Frame Header:
{ # the mask is inverse, for error detection # those flags are supposed to be zero! "2.3.0" => 0x1F1F, # 0xD0D0 , "2.4.0" => 0x8FB0 # 0x704F , }
- FRAME_HEADER_FLAGS =
{ "2.3.0" => { "TagAlterPreservation" => 0x8000 , "FileAlterPreservation" => 0x4000 , "ReadOnly" => 0x2000 , "Compression" => 0x0080 , "Encryption" => 0x0040 , "GroupIdentity" => 0x0020 , } , "2.4.0" => { "TagAlterPreservation" => 0x4000 , "FileAlterPreservation" => 0x2000 , "ReadOnly" => 0x1000 , "GroupIdentity" => 0x0040 , "Compression" => 0x0008 , "Encryption" => 0x0004 , "Unsynchronisation" => 0x0002 , "DataLengthIndicator" => 0x0001 , } }
- FRAMETYPE2FRAMENAME =
the FrameTypes are not visible to the user - they are just a mechanism to define only one parser for multiple FraneNames..
{ "TEXT" => %w(TENTGROUP TITLE SUBTITLE ARTIST BAND CONDUCTOR MIXARTIST COMPOSER LYRICIST LANGUAGE CONTENTTYPE ALBUM TRACKNUM PARTINSET ISRC DATE YEAR TIME RECORDINGDATES ORIGYEAR BPM MEDIATYPE FILETYPE COPYRIGHT PUBLISHER ENCODEDBY ENCODERSETTINGS SONGLEN SIZE PLAYLISTDELAY INITIALKEY ORIGALBUM ORIGFILENAME ORIGARTIST ORIGLYRICIST FILEOWNER NETRADIOSTATION NETRADIOOWNER SETSUBTITLE MOOD PRODUCEDNOTICE ALBUMSORTORDER PERFORMERSORTORDER TITLESORTORDER INVOLVEDPEOPLE), "USERTEXT" => "USERTEXT", "WEB" => %w(WWWAUDIOFILE WWWARTIST WWWAUDIOSOURCE WWWCOMMERCIALINFO WWWCOPYRIGHT WWWPUBLISHER WWWRADIOPAGE WWWPAYMENT) , "WWWUSER" => "WWWUSER", "LTEXT" => "TERMSOFUSE" , "PICTURE" => "PICTURE" , "UNSYNCEDLYRICS" => "UNSYNCEDLYRICS" , "COMMENT" => "COMMENT" , "BINARY" => %w(PLAYCOUNTER CDID) , # For the following Frames there are no parser stings defined .. the user has access to the raw data # The following frames are good examples for completely useless junk which was put into the ID3-definitions.. what were they smoking? # "UNPARSED" => %w(UNIQUEFILEID OWNERSHIP SYNCEDTEMPO MPEGLOOKUP REVERB SYNCEDLYRICS CONTENTGROUP POPULARIMETER GENERALOBJECT VOLUMEADJ AUDIOCRYPTO CRYPTEDMETA BUFFERSIZE EVENTTIMING EQUALIZATION LINKED PRIVATE LINKEDINFO POSITIONSYNC GROUPINGREG CRYPTOREG COMMERCIAL SEEKFRAME AUDIOSEEKPOINT SIGNATURE EQUALIZATION2 VOLUMEADJ2 MUSICIANCREDITLIST INVOLVEDPEOPLE2 RECORDINGTIME ORIGRELEASETIME ENCODINGTIME RELEASETIME TAGGINGTIME) }
- VARS =
0
- PACKING =
1
- FRAME_PARSER =
STILL NEED TO GET MORE TEST-CASES! e.g. Japanese ID3-Tags! or other encodings.. seems like i have no version 2.4.x ID3-tags!! If you have some, send them my way!
{ "TEXT" => [ %w(encoding text) , 'CZ*' ] , "USERTEXT" => [ %w(encoding description value) , 'CZ*Z*' ] , "PICTURE" => [ %w(encoding mimeType pictType description picture) , 'CZ*CZ*a*' ] , "WEB" => [ "url" , 'Z*' ] , "WWWUSER" => [ %w(encoding description url) , 'CZ*Z*' ] , "LTEXT" => [ %w(encoding language text) , 'CZ*Z*' ] , "UNSYNCEDLYRICS" => [ %w(encoding language content text) , 'Ca3Z*Z*' ] , "COMMENT" => [ %w(encoding language short long) , 'Ca3Z*Z*' ] , "BINARY" => [ "binary" , 'a*' ] , "UNPARSED" => [ "raw" , 'a*' ] # how would we do value checking for this? }
- Symbol2framename =
MODULE VARIABLES
ID3::SUPPORTED_SYMBOLS
- Framename2symbol =
Hash.new
- FrameType2FrameName =
ID3::FRAMETYPE2FRAMENAME
- FrameName2FrameType =
FrameType2FrameName.invert
- @@RCSid =
CONSTANTS
'$Id: id3.rb,v 1.2 2004/11/29 05:18:44 tilo Exp tilo $'
Class Method Summary collapse
-
.hasID3tag?(filename) ⇒ Boolean
—————————————————————————- hasID3tag? returns string with all versions found, space separated returns false otherwise.
-
.hasID3v1tag?(filename) ⇒ Boolean
—————————————————————————- hasID3v1tag? returns string with version 1.0 or 1.1 if tag was found returns false otherwise.
-
.hasID3v2tag?(filename) ⇒ Boolean
—————————————————————————- hasID3v2tag? returns string with version 2.2.0, 2.3.0 or 2.4.0 if tag found returns false otherwise.
-
.removeID3v1tag(filename) ⇒ Object
—————————————————————————- removeID3v1tag returns nil if no v1 tag was found, or it couldn’t be removed returns true if v1 tag found and it was removed..
Class Method Details
.hasID3tag?(filename) ⇒ Boolean
hasID3tag?
returns string with all versions found, space separated
returns false otherwise
400 401 402 403 404 405 406 407 408 |
# File 'lib/id3.rb', line 400 def ID3.hasID3tag?(filename) v1 = ID3.hasID3v1tag?(filename) v2 = ID3.hasID3v2tag?(filename) return false if !v1 && !v2 return v1 if !v2 return v2 if !v1 return "#{v1} #{v2}" end |
.hasID3v1tag?(filename) ⇒ Boolean
hasID3v1tag?
returns string with version 1.0 or 1.1 if tag was found
returns false otherwise
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'lib/id3.rb', line 355 def ID3.hasID3v1tag?(filename) hasID3v1tag = false # be careful with empty or corrupt files.. return false if File.size(filename) < ID3v1tagSize f = File.open(filename, 'r') f.seek(-ID3v1tagSize, IO::SEEK_END) if (f.read(3) == "TAG") f.seek(-ID3v1tagSize + ID3v1versionbyte, IO::SEEK_END) c = f.getc; # this is character 125 of the tag if (c == 0) hasID3v1tag = "1.1" else hasID3v1tag = "1.0" end end f.close return hasID3v1tag end |
.hasID3v2tag?(filename) ⇒ Boolean
hasID3v2tag?
returns string with version 2.2.0, 2.3.0 or 2.4.0 if tag found
returns false otherwise
381 382 383 384 385 386 387 388 389 390 391 392 393 |
# File 'lib/id3.rb', line 381 def ID3.hasID3v2tag?(filename) hasID3v2tag = false f = File.open(filename, 'r') if (f.read(3) == "ID3") major = f.getc minor = f.getc version = "2." + major.to_s + '.' + minor.to_s hasID3v2tag = version end f.close return hasID3v2tag end |
.removeID3v1tag(filename) ⇒ Object
removeID3v1tag
returns nil if no v1 tag was found, or it couldn't be removed
returns true if v1 tag found and it was removed..
in the future:
returns ID3.Tag1 object if a v1 tag was found and removed
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
# File 'lib/id3.rb', line 418 def ID3.removeID3v1tag(filename) stat = File.stat(filename) if stat.file? && stat.writable? && ID3.hasID3v1tag?(filename) # CAREFUL: this does not check if there really is a valid tag, # that's why we need to check above!! newsize = stat.size - ID3v1tagSize File.open(filename, "r+") { |f| f.truncate(newsize) } return true else return nil end end |