Mp3TagFS
FUSEじゃねーのだけど。DokanというWINDOWS用のFUSE的なもの用なのだけど。
でもたぶんちょっといじればFUSE用になるはず。
えーとMp3のTagでファイルシステムを作ります。指定したディレクトリ以下のMP3をさらい、
タグを読み込んで"/アーティスト名/アルバム/曲"という階層を作ります。
iPodがさー、ファイルネームを独自形式で保存するのでそっから取り出したい場合、
こんなんあればいいなあと思って作った。
Dokanとmp3infoに依存します。別途入れてください。
Dokan: user-mode file system for Windows
http://rubyforge.org/projects/ruby-mp3info
#!ruby -Ku require 'dokanfs' require 'delegate' class DokanProxy def read(path, offset, length, fileinfo) return "" unless @root.file?(path) if @root.respond_to?(:read_offset) @root.read_offset(path, offset, length) else str = @root.read_file(path) if offset < str.length str[offset, length] else false end end end end class InsensitiveString < DelegateClass(String) def hash __getobj__.downcase.hash end def eql?(oth) __getobj__.downcase.eql?(oth.downcase) end def ==(oth) eql?(oth) end end class Mp3Tag require 'mp3info' require 'jcode' require 'kconv' def cleaning(s) InsensitiveString.new(s.gsub(/[\/\\:]/, "_").kconv(Kconv::SJIS)) end def initialize(path) @map = Hash.new Dir.glob(path+"/**/*.mp3").each{|filename| p filename info = Mp3Info.new(filename) tag = info.tag tag2 = info.tag2 ar = tag.artist || tag2.TP1 || '不明なアーティスト' al = tag.album || tag2.TAL || '不明なアルバム' ti = tag.title || tag2.TT2 || '不明な曲' artist_album = ((@map[cleaning(ar)] ||= {})[cleaning(al)] ||= {}) i = 0; tmp = ti while artist_album[title = cleaning(tmp+".mp3")] tmp = "%s-%04d" % [ti, i+=1] end artist_album[title] = filename } end def split(path) path.split("/")[1..-1].to_a.map{|e| InsensitiveString.new(e)} end def contents path if path == "/" @map.keys else a = split(path) case a.size when 1 @map[a[0]].keys when 2 @map[a[0]][a[1]].keys else [] end end.compact end def file? path a = split(path) a.to_a.size == 3 && @map[a[0]][a[1]][a[2]] end def directory? path a = split(path) case a.size when 0 true when 1 @map[a[0]] when 2 @map[a[0]][a[1]] end end def read_offset(path, offset, len) a = split(path) open(@map[a[0]][a[1]][a[2]], 'rb'){|port| port.pos = offset return port.read(len) } end def size path a = split(path) file?(path) ? FileTest.size(@map[a[0]][a[1]][a[2]]) : 0 end end if __FILE__ == $0 DokanFS.set_root(Mp3Tag.new(ARGV[0])) DokanFS.mount_under("r") DokanFS.run end