From: Matthew Moss Date: 2007-08-30T08:56:28+09:00 Subject: Re: [QUIZ] ID3 Tags (#136) I've been extremely busy lately, but I wanted to give this one a try. This solution is not complete as far as the problem specification goes, but my bit o' metaprogramming-type stuff works, though I'd have liked to push it further. class ID3 @@recLen = 0 def ID3.field(name, len, flags=[]) class_eval(%Q[ def #{name} @data[#{@@recLen}, #{len}].strip end ]) unless flags.include?(:readonly) class_eval(%Q[ def #{name}=(val) # need to pad val to len @data[#{@@recLen}, #{len}] = val.ljust(#{len}, "\000") end ]) end @@recLen += len end # -------------------------------------------------------------- # name, length, flags field :sig, 3, [:readonly] field :song, 30 field :album, 30 field :artist, 30 field :year, 4 field :comment, 30 field :genre, 1 TAG_SIG = "TAG" TAG_SIZE = @@recLen raise "ID3 tag size not 128!" unless TAG_SIZE == 128 # -------------------------------------------------------------- def ID3.createFromBuffer(buffer) ID3.new(buffer) end def ID3.createFromFile(fname) size = File.size?(fname) raise "Missing or empty file" unless size raise "Invalid file" if size < TAG_SIZE # Read the tag and pass to createFromBuffer open(fname, "rb") do |f| f.seek(-TAG_SIZE, IO::SEEK_END) createFromBuffer(f.read(TAG_SIZE)) end end # -------------------------------------------------------------- def initialize(data) @data = data raise "Wrong buffer size" unless @data.size == TAG_SIZE raise "ID3 tag not found" unless self.sig == TAG_SIG end end id = ID3.createFromFile("maple-leaf-rag.mp3") puts id.song