iTunesに10GB以上曲が入っていてiPod nanoに入りきらないので、スマートプレイリストでランダムで曲を突っ込んでいる。しかしランダムに突っ込むと、アーティスト→アルバムと選択したときにそのアルバムに入ってる曲が少ないため、目的の曲がなくてがっかりするパターンが多い。そこで、いっそのこと曲をランダムに突っ込むのではなく、アルバムをランダムで選んで、その中に入ってる曲をまるごとiPodに突っ込もうと考えた。
#!/usr/local/bin/perl
use utf8;
use Encode;
use strict;
use Mac::AppleScript qw(RunAppleScript);#=======================================
# サブ
#=======================================
# カナと濁点が別れてるのを戻す
sub kana_change($$){
my $s;
if($_[0]){
$s = unpack('U*', $_[0]);
$s +=1;
}elsif($_[1]){
$s = unpack('U*', $_[1]);
$s +=2;
}
return pack('U*', $s);
}
#=======================================
# メイン
#=======================================
# iTunesの音楽ディレクトリ
my $dir = '/XXXXXX/iTunes/iTunes Music/';
# つっこむアルバムの枚数
my $album_num = 10;
local *DIR;
# iTunesが起動してなかったら終了
(my $has_itunes_launched = qx{ps -x -c -o "command" | grep -c '^iTunes¥$'}) =~ tr/¥r¥n//d;
exit if(! $has_itunes_launched);
# ディレクトリを舐めてアーティストのリストを出す
my @artist_dirs;
opendir(DIR, $dir) || die;
while(my $f = readdir(DIR)){
next if($f =~ /^¥./ || ! -d ($dir . $f));
push(@artist_dirs, $dir . $f)
}
closedir(DIR);
# さらにもぐってアルバムのリストを出す
my @albums;
foreach my $art_dir(@artist_dirs){
opendir(DIR, $art_dir) || die;
while(my $f = readdir(DIR)){
next if($f =~ /^¥./ || ! -d ($art_dir . '/' . $f));
$f = Encode::decode('utf8', $f);
$f =~ s/"/¥¥"/g;
# 正規化されちゃってるので戻す
$f =~ s/([うか-こさ-そた-とは-ほウカ-コサ-ソタ-トハ-ホゝヽ])¥x{3099}|([は-ほハ-ホ])¥x{309A}/kana_change($1, $2)/ge;
push(@albums, $f)
}
closedir(DIR);
}
# アルバムをランダムで選択
foreach(0 .. $#albums){
my $n = int(rand() * @albums);
my $tmp = $albums[$n];
$albums[$n] = $albums[$_];
$albums[$_] = $tmp;
}
# AppleScriptを作る
my $script = sprintf(<<__APPLE__, join(' or ', map {qq/album is "$_"/} @albums[0 .. $album_num - 1] ) );
tell application "iTunes"
activate
try
display dialog "iPod投入曲(気紛)プレイリストを作成しますか?"
set this_playlist to playlist "iPod投入曲(気紛)"
display dialog "プレイリストを作成中です。" buttons {""} default button 1 giving up after 1
tell source "ライブラリ"
-- 曲を削除
tell this_playlist
delete every track
end tell
-- 該当するアルバムのみ追加
tell playlist "ライブラリ"
duplicate (every track whose %s) to this_playlist
end tell
end tell
display dialog "完了しました。" buttons {"OK"} default button 1 giving up after 2
on error error_message number error_number
if the error_number is not -128 then
beep
display dialog error_message buttons {"OK"} default button 1
end if
end try
end tell
__APPLE__
# 実行
RunAppleScript(encode('cp932', $script));
AppleScriptはこちらで、ファイル名の正規化への対処はこちらをお借りしました。感謝です。
AppleScriptを見つけたんで、こりゃあ簡単かなと思ったらかなりハマり。まず、ファイル名のUNICODEをアップルスクリプトのsjisにしようと思ったら、「が」とかが「か゛」みたいに正規化ってやつがされてるらしく、まずそこで苦戦。
で、つぎにLibraryフォルダにこのスクリプトを書き出してみたのだけど、iTunesから実行できずにハマり。どうやら、スクリプトエディタでコンパイルしないと実行できる形式にはならないみたい。しかたないから、Mac::AppleScriptの力を借りてperlから直接実行。CPANは偉大です。