BibTeX から iTunes へ

以前,PDF の管理を iTunes でできるという記事を /.-j で読んだ.フォルダ指向でなく属性指向のインタフェースで使い勝手がいいという.なんとなく気になってた.

試しに手元の数個の PDF を放り込んでみたが,確かに検索やソートが使いやすい.うん,悪くない.



で,本格的に使おうとしたときに障害になるのが,ファイルのプロパティをどう入力するか,である.手持ちの PDF は論文が多いのだけど,曲名=論文タイトル,アーティスト=著者,アルバム名=書誌名…みたいなのを数百件も手で入力するなんてヤダ.

/.-j でも同意見がちらほら.普段は BibTeX のエントリを Perl に喰わせてエセ検索とかしてるので,このデータベースをなんとか使いたい.調べると iTunes ではタブ区切りテキストや XML 形式の曲リストをインポートできるらしい.

ていうことで,Perl でなんとかなりそうなので,BibTeX ファイルを読み込んで iTunes 用インポートファイルを吐き出すようなものを,やっつけ仕事で作ってみた.Perl レベル 4 なのでそのつもりで(ぉ.なお,インポートファイルはタブ区切りテキストです.iTunes の扱う XML は仕様がまるで謎だったので.



なお,以下ではというやや妙な設定になってます.



では,とりあえず Text::BibTeX というものを入れて手を抜く.あとは Perl レベル 3 くらいの人であればすぐに書ける.

まず iTune インポートファイル用のヘッダを出力.これをはじめ,iTunes に喰わせるテキストは SJIS,CL+LF でないといけない.

$header = "名前\tアーティスト\t作曲者\tアルバム\t分類\tジャンル\tサイズ\t時間\tディスク番号\tディスク数\tトラック番号\tトラック数\t年\t変更日\t追加日\tビットレート\tサンプルレート\t音量調整\t種類\tイコライザ\tコメント\t再生回数\t最後に再生した日\tマイレート\t場所\x0D\x0A";
 jcode::convert(\$header, 'sjis');
print $header;

次に bib ファイルの読み込み.ここで気をつけないといけないのは,bib ファイルは EUC で書かれてないといけない.必要なら前段で文字コード変換する.Perl でのスマートな方法が思い付かないので略(ぉ.

$bibfile = new Text::BibTeX::File "hoge.bib";
$bibfile->set_structure ('Bib');
while ($entry = new Text::BibTeX::Entry $bibfile)
{
    &action;
}

で,sub action の中ではまず,

	warn "error in input" unless $entry->parse_ok;
	my $type = $entry->type;
	
	my $key = $entry->key;                  # only for BTE_REGULAR metatype
	my $num_fields = $entry->num_fields;
	my @fieldlist = $entry->fieldlist;
	my $title = $entry->get ('title');
	my $year = $entry->get('year');
	my $vol = $entry->get('volume') unless ( $entry->get('volume') =~ /\D/ );
	my $num = $entry->get('number') unless ( $entry->get('number') =~ /\D/ );
	my $pages = $entry->get('pages');
	if ( $entry->exists ('journal') ){
	    my $journal = $entry->get('journal');
	}
	if ( $entry->exists ('booktitle') ){
	    my $journal = $entry->get('booktitle');
	}
	my $comment = $entry->get('comment');
	
	if ( $entry->exists ('author') ){
	    my @authors = $entry->split ('author');
	    ($first_author) = $entry->names ('author');
	} else {
	    my @authors = $entry->split ('editor');
	}
		
	my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev,
	    $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat( "$pdfdir$key.pdf" );

雑誌によっては,数字以外の文字が含まれる巻号だったりしますが (J82-D-II とかww),そういうのは省いてます.iTunes のアルバム番号エントリは数字以外許さないので.



次に,ファイル情報から出力をでっちあげます.

	if ( $size ne "" ){
	    
	    my $pdfpath = "$pdfdirwin$key\.pdf";
	    	    
	    my @mdate = localtime( $mtime );
	    my $mt = sprintf("%d/%02d/%02d %d:%d",
			     $mdate[5]+1900, $mdate[4]+1, $mdate[3], $mdate[2], $mdate[1]);
	    my @cdate = localtime( $ctime );
	    my $ct = sprintf("%d/%02d/%02d %d:%d",
			     $cdate[5]+1900, $cdate[4]+1, $cdate[3], $cdate[2], $cdate[1]);
	    my @adate = localtime( $atime );
	    my $at = sprintf("%d/%02d/%02d %d:%d",\
			     $adate[5]+1900, $adate[4]+1, $adate[3], $adate[2], $adate[1]);
	    	    
	    my $output = "$title\t@authors\t\t$journal\t$pages\t$type\t$size\t\t$vol\t\t$num\t\t$year\t$mt\t$ct\t\t\t\tPDF 書類\t\t$comment\t\t\t\t$pdfpath\x0D\x0A";
	    
	  jcode::convert(\$output, 'sjis', 'euc');
	    print $output;
	    
        }

ctime,mtime,atime はなくても動く.ていうか所詮合ってないので,単なる気休め.



で,最後にこんなことを書くと怒られそうなのですが,なぜか手元の環境では年号が正しく iTunes で読めません.出力したテキストファイルは合ってるはずなんだけど.謎.

あと,これをやると iTunes の「ジャンル」の項目が汚くなるのも問題.Rocks とか Classics の中に inproceedings とか入ってきちゃうので.なので,スクリプトを書いただけで満足して,結局活用してません(激ぉ