2011/11/12

Tutorial MacRuby

Tutorial: OS X automation with MacRuby and the Scripting Bridge

One more for the road

以降にある iTunes のサンプルを実行すると

... `<main>': undefined method `playlists' for nil:NilClass (NoMethodError)


playlists がない?
なーんてことはなくて単に日本語システムだからだった。
要素名を日本語に変えればよいのだった。

...
  .find {|s| s.name == "ライブラリ"}
  .playlists.find {|p| p.name == "トップ 25"} #Top 25 Most Played"}
...


この内容を理解する為、基本的な AppleScript を動かす。

 tell application "iTunes"
  repeat with i in playlists
    if name of i is "ミュージック" then
      get tracks
    end if
  end repeat
end tell

AppleScript Editor.app のイベントログで
playlists の要素や tracks の属性を確認できた。
sources にアクセスしなくても、playlists を獲得できた。

MacRuby でも playlists 要素を目視したい為...

framework "ScriptingBridge"

i = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")
i.sources.select{|x|
  x.playlists.each{|y|
    puts y.name
    if y.name ==  "トップ 25" # "トップレート", "ミュージック"
      songs = y.tracks.sort{|t1,t2| t2.playedCount <=> t1.playedCount}
      # songs[0..2].map{|t| puts "#{t.artist} - #{t.name} (#{t.playedCount})"}
    end
  }
}

puts y.name でプレイリスト名一覧を確認できた。

ライブラリ
ミュージック
ムービー
テレビ番組
Podcast
iTunes U
ブック
iTunes DJ
90 年代ミュージック
クラシック音楽
トップ 25
トップレート
ミュージックビデオ
最近再生した項目
最近追加した項目
ラジオ


書き換えながらいろいろ試す。

framework "ScriptingBridge"

i = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")
ary = i.sources.map{|x| x.playlists}.flatten
top25 = ary.find{|i| i.name == "トップ 25"}
songs = top25.tracks.sort{|t1,t2| t2.playedCount <=> t1.playedCount}
songs.find_all{|t| t.rating > 2}.map{|t| puts "#{t.artist} - #{t.name} (#{t.playedCount})"}


Ruby らしい(つもりの)書き方へ。

framework "ScriptingBridge"

class MyiTunes
  def initialize(str)
    exit if (str.empty? or str.nil?)
    @str = str
    # iTunes Object
    i = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")
    # playlist Object
    @ary = i.sources.map{|x| x.playlists}.flatten
    @songs = @ary.find{|i| i.name == @str}.tracks
  end

  def debug
    @ary.each{|x| puts x.name}
  end

  def view
    print "-- #{@str}\n"
    find_all
    count_sort
    to_s
  end

  private
  def count_sort
    @songs = @songs.sort {|t1,t2| t2.playedCount <=> t1.playedCount}
  end

  def find_all
    @songs = @songs.find_all{|t| t.rating > 60}
  end

  def to_s
    @songs.each_with_index{|x,n|
      break if n > 2
      puts "#{x.artist} - #{x.name} (#{x.playedCount}) [#{x.rating}]"
    }
  end
end

MyiTunes.new("トップ 25").view
# MyiTunes.new("トップ 25").debug

実行結果

-- トップ 25
Glenn Gould - Bach: Goldberg Variations, BWV 988 - Aria (5) [100]
Glenn Gould - Bach: Goldberg Variations, BWV 988 - Var. 7 (5) [60]
Glenn Gould - Bach: Goldberg Variations, BWV 988 - Var. 5 (4) [80]
% 


MyiTunes クラスは
"トップ25" から、
星が3つ以上の曲を抽出し、
再生回数順にソートし
3行出力したら終わる。

.rating
に注意を払っていなかった。
puts 表示させてよくみてみると
星が 5つだと 100で、
星が 4つだと 80 で、
星が 3つだと 60 に、
なっていた。
星が3つ以上( > 60 )に変えた。
# t.rating > 60

iTunes.app 環境設定で表示する項目を減らして
MyiTunes.new("トップ 25").debug
を実行すると...正しく捕獲できた。

ライブラリ
ミュージック
ブック
90 年代ミュージック
クラシック音楽
トップ 25
トップレート
ミュージックビデオ
最近再生した項目
最近追加した項目
% 

MyiTunes.new("ミュージック")
でも OK だった。

-- 追記
OS X 10.7.2 で自力で MacRuby をインストールしていない為
/System/Library/PrivateFrameworks/MacRuby.framework/Versions/A/usr/bin/macruby
を使った。

最後に、~/Library/Logs/CrashReporter で
MacRuby がクラッシュしていないかみてみたが
大丈夫だった。

[2011-11-12]
最短?

i = SBApplication.applicationWithBundleIdentifier("com.apple.iTunes")
top25 = i.sources.flat_map{|x| x.playlists}.find{|t| t.name == "トップ 25"}
p top25.name
songs = top25.tracks
p songs.size
=>
"トップ 25"
25


[2011-11-22]
続き

0 件のコメント: