iTunesで最近聞いた曲をブログに表示する(Perl使用)

さんざん既出なモジュールだろうけど、
PerlXMLパーサは遅いのが多いらしいので正規表現で超決め打ちで書いた。
iTunesXMLの構造がもう少しまともだったらこんな事しなくていいんだろうけどなぁ。
あとAPIもメンバー制になってみれなくなってめんどくさかったので。
ただ、メンテは大変めんどくさい。
相変わらず汚いです。

#!perl

use utf8;
use strict;
use Dumpvalue;
use File::Spec;
use File::HomeDir::Windows;
use LWP::Simple;

my $path = File::HomeDir::Windows->my_music;
my $file = File::Spec->catfile($path, 'iTunes', 'iTunes Music Library.xml');

my @recent_playlist;
my %track_list;
my $last_id = -1;

while (1) {
  # ファイル操作
  open my $data, $file;
  while (my $line = <$data>) {
    # 処理の開始
    if ($line =~ /^<dict>$/) {
      while (my $line = <$data>) {
        # 楽曲の取得
        if ($line =~ /^\t<key>Tracks<\/key>$/) {
          get_music($data);
        }
        # プレイリストの取得
        # デフォルトのとか,Geniusとか,最近再生〜とか,最近追加〜など,左メニューに表示してるやつら
        if ($line =~ /^\t<key>Playlists<\/key>$/) {
          get_playlist($data);
        }
      }
    }
  }
  close $data;
  undef($data);
  
  if ($recent_playlist[0] != $last_id) {
    print $track_list{$recent_playlist[0]}->{Name}, $/;
    my $result = get("表示するファイル出力させる");
    #if (is_error($result)) {
    #  die('oops');
    #}
    $last_id = $recent_playlist[0];
  }
  else {
    print "-\n";
  }
  undef(@recent_playlist);
  undef(%track_list);

  sleep(10);
}

# リスト表示
#foreach my $track_id(@recent_playlist) {
#  print $track_list{$track_id}->{Name}, " by ", $track_list{$track_id}->{Artist}, $/;
#}

exit;

sub get_music {
  my $data = shift;
  # <dict>の部分を省略
  my $line = <$data>;
  # 楽曲の取得開始
  while (my $line = <$data>) {
    # 楽曲の取得終了か?
    if ($line =~ /^\t<\/dict>$/) {
      last;
    }
    #my $id = -1;
    ## key
    #if ($line =~ /^\t\t\t<key>([0-9]*?)<\/key>$/) {
    #  $id = $1;
    #}
    # <dict>の部分を省略
    $line = <$data>;
    # dictの中身
    my $track_id;
    while (!((my $line = <$data>) =~ /^\t\t<\/dict>$/)) {
      my($key, $val) = ($line =~ /<key>(.*?)<\/key><[\w]+?>(.*?)<\/[\w]+?>/);
      if ($key eq 'Track ID') {
        $track_id = $val;
        $track_list{$val} = {};
      }
      elsif($key eq 'Artist' || $key eq 'Name') {
        $track_list{$track_id}->{$key} = $val;
      }
    }
  }
}

sub get_playlist {
  my $data = shift;
  # <array>の部分を省略
  my $line = <$data>;
  while (my $line = <$data>) {
    # ライブラリ、Genius、Alternative Plan、トップ25、最近追加した項目、などは無視
    my $str = "\t\t\t<key>Name<\/key><string>最近再生した項目<\/string>";
    utf8::encode($str);
    if ($line =~ /^$str$/) {
      # Playlist Itemsまでの行は無視
      while (my $line = <$data>) {
        if ($line =~ /^\t\t\t<key>Playlist Items<\/key>$/) {
          # <array>は無視
          $line = <$data>;
          # 最近再生したアイテムの取得開始
          while (my $line = <$data>) {
            # リストの取得終了か?
            if ($line =~ /^\t\t\t<\/array>$/) {
              last;
            }
            unless ($line =~ /dict>$/) {
              my($track_id) = ($line =~ /\t\t\t\t\t<key>Track ID<\/key><integer>([\d]*?)<\/integer>$/);
              push(@recent_playlist, $track_id);
            }
          }
          last;
        }
      }
    }
  }
}

1;