2011/11/22

iTunes: MacRuby で重複する曲を削除

先日
MacRuby で iTunes から重複する曲を削除するものを作りました。
https://gist.github.com/1382271
(OS X 10.7.2 限定)

-- 参考にさせていただいたサイト

# ファイルを移動させる際の条件など大変参考になりましたし、
# MacRuby についての情報もいろいろありました。
iTunesに重複登録されている音楽ファイルを削除する - Watsonのメモ

# iTunes.app に下記のような機能があったことをこれまで知りませんでした。
iTunes ライブラリで重複した項目を検索し、削除する方法

-- 当初、最も悩んだこと

track.delete
を実行すると なぜか MacRuby がクラッシュしました。
MacRuby バージョンは

% macruby -v
MacRuby 0.11 (ruby 1.9.2) [universal-darwin11.0, x86_64]


重複する曲が 20 個以上あるとき
playlist.tracks の曲を each でまわし一定の条件を満たしたタイミングで
track.delete するとクラッシュしました。
こんな感じ。

myplaylist.tracks.each{|x|
  if ...
  # x がなにかの条件をみたしたら
  x.delete
  # この瞬間にクラーッシュ!
}


それで、オブジェクトを探ってみることに...

test.rb

framework "ScriptingBridge"

i = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")
a = i.sources[0].userPlaylists.find{|x| x.name ==  "ミュージック"}.tracks
p b = a[0]
p c = a[0]
p b.equal?(c)

#=>

% macruby test.rb
false

なんと false がかえってきました。
b, c は object としてはイコールでは『ない』とのこと。
a は1度しか定義していないにもかかわらず...。

例えば、Ruby 1.9 では

a = ["a","b","c"]
b = a[0]
c = a[0]
p b.equal?(c)

#=>

% ruby193 -v aaa.rb
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0]
true

true がかえってきます。

MacRuby のこの件について理解できておりませんが、ともかく
この事が原因でクラッシュをひきおこしているのかも? と考え
一意の曲オブジェクトを「確実」に指名する方法をとることにしました。
要は

track.databaseID

を使うことにしました。

こんな感じです。

条件をみたした 曲オブジェクトの databaseID を hash に溜め込んでから、
hash を each でまわしつつ
その都度 fileTracks から 指定した databaseID に基づいて曲オブジェクトを検索し
検出できたら
.delete
を実行...

      @h.each{|k,v|
        t = @filetracks.find{|x| x.databaseID == k}
        next unless t
        t.delete
      }


このようにしてみたところ .delete を実行しても
クラッシュしなくなりました。
# あくまでも私の環境下においてでは!です。

# ちなみに .fileTracks と .tracks の 2 種類ありますが
# 上記では .fileTracks を対象にしています。

0 件のコメント: