Dokan(Windows 版 FUSE)で MP3Tunes Locker をマウントしてみる(失敗)
Dokan という Windows 版 FUSE を以下のサイトで見つけ、
非常におもしろそうだったのでとりあえず MP3Tunes Locker をマウントしてみることにした。
2008-05-27
locker.rb
require 'lib/dokanfs' require 'lib/mp3tunes' require 'kconv' require 'open-uri' class Locker def initialize @mp3tunes = MP3Tunes.new.login end def contents path if path == "/" @artists = @mp3tunes.artists unless @artists @artists_name = @artists.map do |a| a[0].tosjis end return @artists_name elsif path.split("/").size == 2 @artists.each do |ar| if ar[0].tosjis == path.split("/")[1] @albums = @mp3tunes.albums(ar[1]) #unless @albums @albums_name = @albums.map do |al| al[0].tosjis end return @albums_name end end elsif path.split("/").size == 3 @albums.each do |al| if al[0].tosjis == path.split("/")[2] @tracks = @mp3tunes.tracks(al[1]) #unless @tracks @tracks_name = @tracks.map do |tr| tr[:trackTitle].tosjis + ".mp3" end return @tracks_name end end end return [] end def file? path path =~ /mp3/ end def directory? path if path == "/" return true elsif path.split("/").size == 2 return false unless @artists_name return @artists_name.index(path.split("/")[1]) != nil elsif path.split("/").size == 3 return false unless @albums_name return @albums_name.index(path.split("/")[2]) != nil end false end def read_file path return "" unless @tracks if path.split("/").size == 4 @tracks.each do |t| return open(t[:downloadURL]).read if t[:trackTitle].tosjis == path.split("/")[3][0..-5] end end "" end def size path return 4096 unless @tracks if path.split("/").size == 4 @tracks.each do |t| return t[:trackFileSize].to_i if t[:trackTitle].tosjis == path.split("/")[3][0..-5] end end 4096 end end FuseFS.set_root(Locker.new) FuseFS.mount_under("r") FuseFS.run
使い方
- Dokan をインストーラでインストール
- Dokan Ruby バインディング を DokanLibrary 以下に解凍
- sample 以下に locker.rb を lib 以下に mp3tunes.rb をコピー
- mp3tunes.rb のユーザ名とかを編集
- $ruby sample\locker.rb でマウント
- あまりの重さに絶望した!(ファイルの列挙までは行くけどコピーができない…)
失敗の原因
ファイル読み込み時に呼ばれる read_file が異常に重い。
一回のコピーで read_file は何度も呼ばれるらしく、
アクセスがある度に open-uri が MP3 ファイルをフルサイズで
ダウンロードしようとするため、アクセス過多でコピーが失敗する。
解決策としては、FuseFS 互換ライブラリ(dokanfs.rb)の使用をやめ
read_files の引数に offset と length を取る標準 API を使うようにする。
そして offset に従い、resume ダウンロードを行うようにすれば
ファイルのコピーまでは行くと思う(たぶん)
ただし、アーティスト名に"/"が含まれると階層がおかしくなったりという
お粗末なバグはそのまま。
どこかのスーパーハカーがもっとマシなものを作ってくれることに期待!(オイ