#!/usr/bin/ruby -w # -*- ruby -*- require 'pathname' require 'optparse' $verbose = false def quote(str) str.gsub(%r{([\'\"])}) { "\\" + $1 } end def log(msg) puts msg if $verbose end class FlacFile attr_reader :mp3name MP3_FIELDS = { # flac # mp3/id3 'ALBUM' => 'A', 'ARTIST' => 'a', 'DATE' => 'y', 'GENRE' => 'g', 'TITLE' => 's', 'TRACKNUMBER' => 't', 'TRACKTOTAL' => 'T', } def initialize(flacname) @flacname = flacname @mp3name = flacname.sub(%r{.flac$}, '.mp3') end def mp3_exist? Pathname.new(@mp3name).exist? end def encode log "encoding flac to mp3 ..." cmd = "flac -sdc \"#{@flacname}\" | lame -h - \"" + quote(@mp3name) + "\"" log "cmd: #{cmd}" IO.popen(cmd).readlines end def tag mfcmd = "metaflac --export-tags-to=- \"" + quote(@flacname) + "\"" log "mfcmd: #{mfcmd}" fields = Hash.new IO.popen(mfcmd).readlines.each do |line| line.chomp! name, value = line.split('=') fields[name] = value log line end id3tagcmd = "id3tag " id3tags = MP3_FIELDS.sort.collect do |flactag, id3tag| next unless val = fields[flactag] case flactag when 'GENRE' val ||= 9 # 9=metal; 22=death when 'DATE' val = val[0 .. 3] end log "val: #{val}" "-#{id3tag}\"" + quote(val) + "\"" end.compact id3tagcmd << id3tags.join(" ") << "\"" + quote(@mp3name) + "\"" log "id3tagcmd: #{id3tagcmd}" IO.popen(id3tagcmd).readlines end end $retag = false def process(fname) flacfile = FlacFile.new(fname) mp3exists = flacfile.mp3_exist? unless mp3exists flacfile.encode end if !mp3exists || $retag flacfile.tag end end opts = OptionParser.new do |opts| prog = File.basename(__FILE__) opts.banner = "Usage: #{prog} [options] FLACFILE ..." opts.on("--retag", "Tag the MP3 files, without the dependency check") { |$retag| } opts.on("--verbose", "-v", "Verbose output") { |$verbose| } end begin opts.parse!(ARGV) rescue OptionParser::ParseError => e puts e puts opts.banner exit(-2) end args = ARGV args.sort.each do |arg| pn = Pathname.new(arg) if pn.directory? pn.find do |x| if x.file? && x.extname == ".flac" process(x.to_s) end end else process(arg) end end