RSS

初出:2007年1月22日 08:38

mixiミュージックって凄く良いアイデアだと思うんだけど、なんとなくiTunesの中身を覗かれている気がしてイヤなんだよね。ま、そういうこと言いただしたら、例の足あと機能なんて、まさに覗き覗かれってなもんですけどね。mixiミュージックって、再生時間まで表示されるじゃないですか。気にし過ぎなんだろうけど「こいつなんでこんな時間に音楽聴いているの? 仕事してるの?」なんて思われたら、はいその通りですとしか言えませんがな。

でも、iTunesやiPodで再生した曲リストを自動でサイトに公開っていうのは面白い。こんな面白いんだから、mixiだけじゃなく自分のブログでやりたい。そんなわけで、やっちゃいました。このブログのトップページに「本日のiTunes BGM」というのがあって、最新の20曲がリストされています。

この仕組み、実はAjaxです。そう、はじめてのAjax。Google Mapsみたいに派手にグリグリ動くようなものじゃないけど、Ajax。なんでそうしたかを説明するために、まずはどういう手順で実現しているか見てみましょう。

  • iTunesで「最近再生した20曲」(ま、30でも50でもいいんだけど)を抽出するスマートプレイリストを作る
  • 「曲リストを書き出す」というコマンドで、XML形式のテキストをWebサーバ上に書き出す
  • ページにアクセスすると、ブラウザはそのXMLを読み込み、曲名、アーティスト、アルバム発表年を抽出し、HTMLとして表示

XMLを読み込んでHTMLに反映、というのがミソなんだけど、XMLを読み込むのにJavaScriptを使い、処理が重くならないように非同期通信する必要がある。そう、非同期通信でJavaScriptを使ってXMLを操作する。AsynchronousにJavaScriptでXMLする。はい、Ajax、なわけです。

じゃあ実現するためにどっから手を付けようかと悩みましたが、そういう試行錯誤はここでは全部すっ飛ばして、ポイントだけを列挙しましょう。

  • iTunesが書き出すXMLは、Mac OS Xとそのアプリが解釈することを前提としており、Webで使うために作られたわけじゃない。ので、その構造は結構複雑。
  • XMLから必要な要素を指定するために、まずは分かりやすくJavaScriptオブジェクトツリーに展開する必要あり
  • これを実現し、さらにAjaxするための基盤として、Kawa.netさんで配布している「XML.ObjTree」を利用。これがなければ実現は無理でした。多謝。

それで作ったJavaScriptはこれ↓




function RecentPlaylist() {

        var xotree = new XML.ObjTree();
        var xml = 'https://wonderwall.net/blog/keng/itunes.xml';

        var loop = function(tree){
                for( i=0 ; i "+tree.plist.dict.dict.dict[i].string[1]+" ("+tree.plist.dict.dict.dict[i].integer[7]+")";
                        document.getElementById("item"+[i]).innerHTML = tree.plist.dict.dict.dict[i].string[0]+" : "+tree.plist.dict.dict.dict[i].string[1]+" ("+tree.plist.dict.dict.dict[i].integer[7]+")";
                }
        }
        xotree.parseHTTP( xml, {} , loop );             // source to tree

}

innerHTMLを受け取るためのHTML構造はこれ↓

<ul class="arrowtext">
        <li id="item0"></li>
        <li id="item1"></li>
        <li id="item2"></li>
        <li id="item3"></li>
        <li id="item4"></li>
        <li id="item5"></li>
        <li id="item6"></li>
        <li id="item7"></li>
        <li id="item8"></li>
        <li id="item9"></li>
        <li id="item10"></li>
        <li id="item11"></li>
        <li id="item12"></li>
        <li id="item13"></li>
        <li id="item14"></li>
        <li id="item15"></li>
        <li id="item16"></li>
        <li id="item17"></li>
        <li id="item18"></li>
        <li id="item19"></li>
        <li id="item20"></li>
</ul>

はい、これを作るのに、いったいどれくらいの時間を費やしただろう…と思うくらい大変でした。まだこれでも問題があって、iTunesが書き出すXMLは日付でソートされているわけではないのだ。なので、ページに表示されているのは再生順はデタラメです。本当はきちんとソートしてから表示させたいんだけど、とにかく複雑なXMLだから、ソートする仕組みを作るに至りませんでした。そんなことしたら、脳みそがこんがらがって死んじゃうよ。

でも、方法はあるんです。アドビが配布しているAjax用のクラスライブラリに「Spry framework for Ajax」てのがありまして、これを使えばXMLを読み込む際にソートすることなんてのもできるんです。でもいかんせiTunesのXMLは……というわけで、自分でXML構造から設計するときは、ぜひSpry frameworkを使ってみようと思うわけです。まずは「逆引きAdobe Spryリファレンス」で勉強しておきましょう。

この曲リストにアフェリエイトのリンクを自動で張れたらいいなあ。iTunes StoreがAPIを公開してくれたら、そういったこともできるのにね。もしくはiTunes Storeの商品データベースをもっている他サイトが、そういう技術を提供するとか、してくれないかな。

Googleさんは、この記事をこう解釈しました

記事の詳細ページ

記事の全文を表示します。関連するコメントやトラックバックなどもこちらからどうぞ。

本日のBGM

★印があったら「これは聴いてみてほしい!」という推薦曲です。曲名をクリックするとiTunes Storeへジャンプします。

'; // loop through the songs in the array and get 4 fields that I want to see foreach ($songs as $song) { $output .= '
  • '; if ($song["Rating"] == 100){ $output .= ''.$song["Rating"].''; } $output .= '
    '; $output .= '
    '.$song["Name"].''; $output .= '
    '.$song["Artist"].''; $output .= ''.$song["Album"].''; if ($song["Year"]){ $output .= '('.$song["Year"].')'; } $output .= '
  • '; } // end the table $output .= ''; // show my new table print ($output); } ?>

    Now & Then

    Twitter Updates

      OAuthRequest('https://api.twitter.com/1.1/statuses/user_timeline.json','GET',array('screen_name' =>$search_word,'count' =>'3')); //Jsonデータをオブジェクトに変更 $oObj = json_decode($vRequest); //var_dump(json_decode($vRequest)); //オブジェクトを展開 for($i_tweet = 0; $i_tweet < sizeof($oObj); $i_tweet++){ $screen_name = $oObj[$i_tweet] -> {'screen_name'};//ユーザーID $profile_image_url = $oObj[$i_tweet] -> {'profile_image_url'};//プロフィール画像のURL $text = $oObj[$i_tweet] -> {'text'};//ツイート $date = $oObj[$i_tweet] -> {'created_at'};//時間 $tweet_time=strtotime($date);//Unixタイムスタンプ形式に変換 $now_time=time();//現在の時刻をUnixタイムスタンプで取得 $relative_time=$now_time-$tweet_time;//つぶやかれたのが何秒前か if($relative_time<60){//ss $displayTime = $relative_time.'秒前'; }elseif($relative_time>=60 && $relative_time<(60*60)){//mm $displayTime = floor($relative_time/60).'分前'; }elseif($relative_time>=(60*60) && $relative_time<(60*60*24)){//hh $displayTime = floor($relative_time/(60*60)).'時間前'; }elseif($relative_time>=(60*60*24)){//日付 $displayTime = date('n月j日',$tweet_time); } //表示 echo '
    • ' . $text .'' . $displayTime . '
    • '; } ?>
    follow me on Twitter