こんにちは
flex builder でちょっとしたアプリを作ったのでそれの作り方をまとめてみました。
flex をこれから始める人、始めたけど
今ひとつコツがつかめず挫折した人。などの人に参考になればと。
で、今回何を作ったかというと、
「youtube が検索できる player 付きのアプリ」
です。この中に flex で一通りの使い方が色々と盛り込まれているので
一通り理解できれば、色んなアプリを手助けになるのではと思います。
さて、早速、完成画面から。今回はこんなのを作ってみようと思います。

見たい動画を検索窓に入れて、検索ボタンをおすと、左側のリストにyoutubeの検索結果が
サムネイル付きで表示されます。ここでは youtube の APIを利用して
検索結果を取得しています。
次にサムネイルをダブルクリックすると、右側のプレイヤーで動画が再生されます。
これだけです。
それでは、早速始めましょう。

まずは flex builder の体験版をダウンロードしましょう。
adobe flexの HP よりDownload free trial を
選択し、flex builder3の体験版をダウンロードしましょう。
60日間トライアルできます。
私はmac版をダウンロードしましたが、
windowsの方はwindows版をdownloadです。

次にdownloadしたファイルをPCにインストールします。
この部分の説明は割愛.
インストールが終わったらflex builderを起動します。

これから作成するアプリのプロジェクトを作成します.
メニューから[ファイル] - [新規] - [MXMLアプリケーション] を選択します

プロジェクト名を入力します。今回は youtube_player としました。


終了を押すと、元の画面にプロジェクトのひな形が作成されました。
ここから開発をスタートします。
左上のflexナビゲータには各種リソースがあります。
src/youtube_player.mxmlのソースに編集を加えていくことになります。
右のメイン画面にはそのソースが開いた状態になっていると思います。
次にまずはデザインを配置してしまいましょう。今回使う主要なものは
- キーワードを入力する TextInput
- 検索ボタンの Button
- 検索結果を表示する TileList
- 動画を見せる player
基本的にこの4つがあれば、デザインはどんなものでも良いです。
メインパネルの「ソース」と「デザイン」の切り替えで「デザイン」を押して
作ります。(もちろんソースに直に書いてもokです). 私が行った方法を例にあげます

Application(全体) の レイアウトを vertical にする.
ApplicationControlBar を配置し width:100% にする.
その中に TextInput と Button を配置する.
Button のラベルを youtube search にする
次にApplicationControlBarの下部にHDividedBoxを配置する
width:100% height:100%にする
その中に TileList を width:100% height:100%で配置する
この時点で youtube_player.mxmlのソースは
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:ApplicationControlBar width="100%">
<mx:TextInput/>
<mx:Button label="youtube search"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%"></mx:TileList>
</mx:HDividedBox>
</mx:Application>
となっています.では、ちょっとずつ確認しながら作りましょう.
まず TextInputにキーワードを入力して Buttonをクリックしたら Alertがあがるようにしましょう。
そのためには、TextInput に id をつけて Button のクリック動作に関数を割り当てましょう.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
public function send_request():void {
Alert.show(keyword.text);
}
]]>
</mx:Script>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="keyword" />
<mx:Button label="youtube search" click="send_request()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%"></mx:TileList>
</mx:HDividedBox>
</mx:Application>
なにをやったかというと, TextInput に keywordというidを与え、Buttonの click イベントに send_request の関数を与えました。
mx:Script のタグをあたらにもうけ、その中に send_requestの関数を処理を記入しました。
今回は keywordの中身の文字列のAlert を出すのでその処理を記入しました。
(Alertを出すには mx.controls.Alert を import する必要があるのでそれも加えてあります)

ここで実行を一度してみましょう。flex builder上部の緑色の丸いプレイアイコンをクリックするか 実行メニューを選ぶとswfをコンパイルしてブラウザが勝手に起動されると思います。 そこに先ほどデザインしたものが表示され、キーワード窓に適当に入力し、ボタンをクリックしたら Alertダイアログが表示されその中身はキーワード窓で入力したものが表示されていると思います。
さて、次に youtube APIを利用して動画リストを取得するのですが、 youtube APIの仕様を確認しておきましょう. APIにはさまざまなリクエスト方法がありますが、今回使用するのは単純にキーワード検索ですので
http://gdata.youtube.com/feeds/api/videos?vq=[キーワード]
です。実際にブラウザでアクセスしてみるとXMLが取得できると思います.flexにてapiにアクセスする一般的な方法は HTTPServiceを利用することです。先ほどの youtube_player.mxml に
<mx:HTTPService id="youtubeapi"
url="http://gdata.youtube.com/feeds/api/videos" method="GET"
result="youtubeapi_result(event)" />
をまず加えます. 次に先ほど Alertをだしていた関数にsend_request にAPIリクエストを投げる処理を加え、APIの応答が戻ってきたときに呼ばれる(HTTPService関数のresultで指定した)youtubeapi_result関数を作れば、youtubeAPIに flexからリクエストを投げて応答を受け取ったことになります. ここまでで
プログラムは以下になります
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
public function send_request():void {
var uv:URLVariables = new URLVariables;
uv.vq = keyword.text;
youtubeapi.request = uv;
youtubeapi.send();
}
public function youtubeapi_result(event:ResultEvent):void {
Alert.show("get youtube result");
}
]]>
</mx:Script>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="keyword" />
<mx:Button label="youtube search" click="send_request()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%"></mx:TileList>
</mx:HDividedBox>
<mx:HTTPService id="youtubeapi"
url="http://gdata.youtube.com/feeds/api/videos" method="GET"
result="youtubeapi_result(event)" />
</mx:Application>
説明していない部分は, send_request の中の
var uv:URLVariables = new URLVariables;
uv.vq = keyword.text;
youtubeapi.request = uv;
youtubeapi.send();
ですが、 URLVariables クラスを用いると一般的なAPIの引数の &key1=val1&key2=val2 値を
一つの変数で保持できます. 今回は vq=キーワードなので uv.vq = キーワード となります.
後はこの変数を HTTPServiceの request にセットして APIに投げます (send).
ここでもう一度実行してみてください。 検索ボタンをおしてしばらく待つと応答が帰ってくると思います.
さて、youtube からの応答がXML帰ってきました。が中身を知らなければ何もできません. ブラウザでアクセスしてみて応答をソース表示して中身のXMLを一度確認してみましょう. かなり、よーくみると以下の構造をしていることが分かります
<?xml version='1.0' encoding='UTF-8'?>
<feed .....>
しばらく、ヘッダー的なタグが続く
<entry>1件目の動画情報<entry>
<entry>2件目の動画情報<entry>
<entry>3件目の動画情報<entry>
<entry>....<entry>
<entry>n件目の動画情報<entry>
</feed>
さらに、entryの中身は
<entry>
<id>http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg</id>
<published>2007-07-08T04:04:05.000-07:00</published>
<updated>2007-07-08T04:04:05.000-07:00</updated>
<category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='15年目'/>
<category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='YUTAKA'/>
<category scheme='http://schemas.google.com/g/2005#kind' term='http://gdata.youtube.com/schemas/2007#video'/>
<category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='尾崎豊'/>
<category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='OZAKI'/>
<category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='卒業'/>
<category scheme='http://gdata.youtube.com/schemas/2007/keywords.cat' term='アイラブユー'/>
<category scheme='http://gdata.youtube.com/schemas/2007/categories.cat' term='Music' label='Music'/>
<title type='text'>尾崎豊 - 卒業</title>
<content type='text'>尾崎豊 15年目のアイラブユー
2007-04-28
from Japan</content>
<link rel='alternate' type='text/html' href='http://www.youtube.com/watch?v=_EEx3VhloNg'/>
<link rel='http://gdata.youtube.com/schemas/2007#video.responses' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg/responses'/>
<link rel='http://gdata.youtube.com/schemas/2007#video.related' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg/related'/>
<link rel='self' type='application/atom+xml' href='http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg'/>
<author>
<name>sean1965jp</name>
<uri>http://gdata.youtube.com/feeds/api/users/sean1965jp</uri>
</author>
<media:group>
<media:title type='plain'>尾崎豊 - 卒業</media:title>
<media:description type='plain'>尾崎豊 15年目のアイラブユー
2007-04-28
from Japan</media:description>
<media:keywords>15年目, OZAKI, YUTAKA, アイラブユー, 卒業, 尾崎豊</media:keywords>
<yt:duration seconds='411'/>
<media:category label='Music' scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>Music</media:category>
<media:content url='http://www.youtube.com/v/_EEx3VhloNg' type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='411' yt:format='5'/>
<media:content url='rtsp://rtsp2.youtube.com/ChoLENy73wIaEQnYoGVY3TFB_BMYDSANFEgGDA==/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='411' yt:format='1'/>
<media:content url='rtsp://rtsp2.youtube.com/ChoLENy73wIaEQnYoGVY3TFB_BMYESARFEgGDA==/0/0/0/video.3gp' type='video/3gpp' medium='video' expression='full' duration='411' yt:format='6'/>
<media:player url='http://www.youtube.com/watch?v=_EEx3VhloNg'/>
<media:thumbnail url='http://img.youtube.com/vi/_EEx3VhloNg/2.jpg' height='97' width='130' time='00:03:25.500'/>
<media:thumbnail url='http://img.youtube.com/vi/_EEx3VhloNg/1.jpg' height='97' width='130' time='00:01:42.750'/>
<media:thumbnail url='http://img.youtube.com/vi/_EEx3VhloNg/3.jpg' height='97' width='130' time='00:05:08.250'/>
<media:thumbnail url='http://img.youtube.com/vi/_EEx3VhloNg/0.jpg' height='240' width='320' time='00:03:25.500'/>
</media:group>
<yt:statistics viewCount='195171'/>
<gd:rating min='1' max='5' numRaters='133' average='4.95'/>
<gd:comments>
<gd:feedLink href='http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg/comments' countHint='0'/>
</gd:comments>
</entry>
それでは、flexからこのXMLの各要素にアクセスしてみましょう。簡単です。応答が帰ってきたときに
呼ばれるために作った関数 youtubeapi_resultの引数に event:ResultEvent があります。これの
event.result要素がこのXMLになります。なので、例えば entryの5件目のtitle は
event.result.feed.entry[5].group.title
になります。それでは、ひとまず正しくXMLを取得できているか確認するために youtubeapi_result関数を
public function youtubeapi_result(event:ResultEvent):void {
Alert.show(event.result.feed.entry.length);
for(var i:int=0;i<event.result.feed.entry.length;i++) {
Alert.show(event.result.feed.entry[i].group.title);
}
}
として動作確認してみてください。取得した動画の本数とタイトルが順にAlertに表示されると思います.
さて、次はこの結果をTileListにリスト表示させます List, TileList, HorizontalList などの各要素は単純に dataProviderを用いてリスト表示をするのが単純な使い方ですが (flexリファレンス) 検索結果画面とか商品一覧とかの画面ではリストの一つ一つがUIデザインをもつものであることが多いです。そのために、この List系のコンポーネントは itemRenderer というプロパティをもちます。これを使えば、個々のItemの設計を別に定義できます (flexリファレンス)
文字で書くと良くわからないので実際にやってみます。
まず、TileList のタグを
<mx:TileList width="100%" height="100%" dataProvider="{movielist}" itemRenderer="movieitem"
とします. これの意味は TileListの要素はmovielistの変数の値を使うよ. 個々のitemの表示には movieitemコンポーネント (movieitem.mxml) を使うよ. という意味です. movielist (ArrayCollection) も加えた形は下記になります (movielistは Bindable として登録する必要があります).
youtubeapi_resultの処理をmovielistの初期化および entry リストの代入を行うように変更しました.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
[Bindable]
public var movielist:ArrayCollection = new ArrayCollection;
public function send_request():void {
var uv:URLVariables = new URLVariables;
uv.vq = keyword.text;
youtubeapi.request = uv;
youtubeapi.send();
}
public function youtubeapi_result(event:ResultEvent):void {
movielist.removeAll();
for(var i:int=0;i<event.result.feed.entry.length;i++) {
movielist.addItem(event.result.feed.entry[i]);
}
}
]]>
</mx:Script>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="keyword" />
<mx:Button label="youtube search" click="send_request()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%" dataProvider="{movielist}" itemRenderer="movieitem" />
</mx:HDividedBox>
<mx:HTTPService id="youtubeapi"
url="http://gdata.youtube.com/feeds/api/videos" method="GET"
result="youtubeapi_result(event)" />
</mx:Application>
さて、これで実行するとエラーになるはずです. movieitem って何ですか? と怒られてしまいます。
ので、movieitem を作りましょう.

[ファイル] - [新規] - [MXMLコンポーネント] を選択して

ファイル名: movieitem ベース: VBox 幅: 150 高さ:150
で終了すれば movieitem.xml が左上の flexナビゲータに追加されます. この状態で実行するとエラーにはなりません. がまだ何も表示されません が、マウスでTileListをなぞるとitemが置かれている予感がします.
さて、 movielist.xml の記述に入ります. メインの画面を movielist.mxmlに切り替えて Image および Text を配置します。デザインから行っても構いませんが、最終的なソースは
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="150" height="150" horizontalAlign="center">
<mx:Image height="97" width="130" source="{data.group.thumbnail.getItemAt(0).url}"/>
<mx:Text text="{data.group.title}" width="100%" height="100%"/>
</mx:VBox>
になります. Imageはイメージ画像をロードするコンポーネントです. ここで重要なのが, TileListのdataProviderの各要素がこのコンポーネントに渡されるのですが、その各要素は data の変数から
取得できるということです. なので youtube の entry を各要素として TileListのdataProviderに渡しているからこの中では entryのtitleは data.group.title で取得できます. 1つめのサムネイル画像は
data.group.thumbnail.getItemAt(0).url で取得できます (data.group.thumbnail[0].urlとするとバインディングエラーがでるので注意).
ここで実行してみましょう

ひとまずやった!ですね。
ということで応用すれば TileList をほかのに変更すれば縦リスト、横リスト. それに応じてまだ使ってない entryの要をを movieitem.mxml に貼付けていけばどんどんオリジナルな画面になっていきます.
さて、次は player の部分です。そもそもflexで動画を流すのは flv 形式のファイルをVideoDisplayというコンポーネントで再生する形にします. youtubeの各動画のflv形式を取得するのは、まず個々のvideo_idを取得します。これは普通にyoutubeを見るときにURLの中に含まれているので一般的です. APIのXMLの中にも
<entry>
<id>http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg</id>
とあります。この_EEx3VhloNgがvideo_idです。
で、これが分かったら次に こういうホームページの解説をフムフムと参考にさせていただいて, 自前のサーバにちょっとflexからはなれて、
<?php
$curl = curl_init();
curl_setopt ($curl, CURLOPT_URL, "http://www.youtube.com/watch?v=${_GET['video_id']}");
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
$html = curl_exec ($curl);
preg_match('|"video_id": "(.*?)"|', $html, $v);
preg_match('|"t": "(.*?)"|', $html, $t);
print "<url>";
print "http://jp.youtube.com/get_video?video_id=${v[1]}&t=${t[1]}";
print "</url>";
?>
こんなPHPスクリプトを設置します. これは何かというと http://hiyuzawa.jpn.org/api/youtube.php?video_id=_EEx3VhloNg とすれば
<url>
http://jp.youtube.com/get_video?video_id=_EEx3VhloNg&t=OEgsToPDskJkG3phYIjT7JC2IvqXnU3a
</url>
が戻ってくるスクリプトです。この戻りのURLでflvが取得できます.
さて、検索結果のサムネイルをダブルクリックした場合に動画が再生されるようにしたいので、 まず、サムネイルのダブルクリックを検知し、関数が呼ばれる仕組みを実装しましょう.
TileListのプロパティに
doubleClickEnabled="true" doubleClick="playmovie()"
を加えます。 doubleClickEnabledを trueにするのを忘れないようにしてください。それで
playmovie関数を定義すればそれが呼ばれます。今回はもう少し突っ込んで進みましょう。最終的に
やりたいことはタブルクリックしたら1. ダブルクリックしたサムネイルの video_idをしらべて
2.そのvideo_idを先ほどのflvが取得できるURLを獲得できる自作のapiに投げて
3.その応答のURLを動画再生のsourceにセットする
です。なので、1.のダブルクリックしたサムネイルのvideo_idまで取得できるように実装しましょう.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
[Bindable]
public var movielist:ArrayCollection = new ArrayCollection;
public function send_request():void {
var uv:URLVariables = new URLVariables;
uv.vq = keyword.text;
youtubeapi.request = uv;
youtubeapi.send();
}
public function youtubeapi_result(event:ResultEvent):void {
movielist.removeAll();
for(var i:int=0;i<event.result.feed.entry.length;i++) {
movielist.addItem(event.result.feed.entry[i]);
}
}
public function playmovie():void {
var tmp:Array = movielist.getItemAt(tilelist.selectedIndex).id.split('/');
var video_id:String = tmp[tmp.length-1];
Alert.show(video_id);
}
]]>
</mx:Script>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="keyword" />
<mx:Button label="youtube search" click="send_request()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%" dataProvider="{movielist}"
itemRenderer="movieitem"
doubleClickEnabled="true" doubleClick="playmovie()"
id="tilelist" />
</mx:HDividedBox>
<mx:HTTPService id="youtubeapi"
url="http://gdata.youtube.com/feeds/api/videos" method="GET"
result="youtubeapi_result(event)" />
</mx:Application>
playmovieの関数で, tilelist.selectedIndex が何番目の listを今選択しているかが取得できます. (TileListのidをtilelistにしました.) movielist.getItemAt(tilelist.selectedIndex).id でその選択している entryの idタグ部分が
取得できます。このidは<id>http://gdata.youtube.com/feeds/api/videos/_EEx3VhloNg</id> となっている部分なので、実際のvideo_idは最後の/の後ろの部分なので、ちょっと横着して / でsplitして、最後の部分を取得しています. (この部分はもっといい方法があると思います。)
まあ、これで実行してサムネイルをダブルクリックしてみてください. video_idが表示されるはずです.
次にvideo_idが取得できたら、これを自作のAPIに投げて flvのURLが取得できるところまで実装しましょう。APIへのリクエスト&受信はまったくyoutube API の部分と同じ感じです。一気に実装します.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
[Bindable]
public var movielist:ArrayCollection = new ArrayCollection;
public function send_request():void {
var uv:URLVariables = new URLVariables;
uv.vq = keyword.text;
youtubeapi.request = uv;
youtubeapi.send();
}
public function youtubeapi_result(event:ResultEvent):void {
movielist.removeAll();
for(var i:int=0;i<event.result.feed.entry.length;i++) {
movielist.addItem(event.result.feed.entry[i]);
}
}
public function playmovie():void {
var tmp:Array = movielist.getItemAt(tilelist.selectedIndex).id.split('/');
var video_id:String = tmp[tmp.length-1];
var uv:URLVariables = new URLVariables;
uv.video_id = video_id;
flvurlapi.request = uv;
flvurlapi.send();
}
private function flvurlapi_result(event:ResultEvent):void {
Alert.show(event.result.url);
}
]]>
</mx:Script>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="keyword" />
<mx:Button label="youtube search" click="send_request()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%" dataProvider="{movielist}"
itemRenderer="movieitem" doubleClickEnabled="true" doubleClick="playmovie()"
id="tilelist" />
</mx:HDividedBox>
<mx:HTTPService id="youtubeapi"
url="http://gdata.youtube.com/feeds/api/videos" method="GET"
result="youtubeapi_result(event)" />
<mx:HTTPService id="flvurlapi"
url="http://hiyuzawa.jpn.org/api/youtube.php" method="GET"
result="flvurlapi_result(event)" />
</mx:Application>
同じですね. もう一つ HTTPServiceをつくって、ダブルクリックで呼ばれる関数で send して
応答を受信する。event.result.url で <url>http://......</url>の中身が取得できます.さあ、次にplayerを作ります。playerは VideoDisplayという 非常に便利なコンポーネントがありますのでこれを使います. 実は単にメインの画面にこの VideoDisplayを 設置して id="hogehoge" とつけて hogehoge.source = で先ほどのflv のURLをセットすればそれで 再生できてしまうのですが... それだと応用性に欠けるのでplayerを独立したモジュールで作ってみましょう。さっさと再生したい方は上の方法をトライしてみてください.
flvのplayerは別につくるアプリでも使う可能性がある. とか、 再生とか停止とかタイムとかそういうデザインをメインのmxmlに加えると混乱するなどという場合に mxmlファイルを別に定義してそれを読み込む形ができます。ちょうど上の itemRenderer と似ているような感じです。早速playerを独立したmxmlファイルで定義してみましょう.まず、左上のflexナビゲータのsrcのフォルダを右クリックして「新規」-「フォルダー」で module という名前のフォルダーを作ってください. 実際にはこの名前は何でもいいです.
次に, 先ほどの movieitem.mxmlを作っときと同様にメニューから
「ファイル」-「新規」-「MXMLコンポーネント」を選びます.
ファイル名: player ベース: VBox 幅: 250 高さ:250
とします.作成先が module のフォルダの下になるように設定してください.
最終的には左のようになればokです
さて、ではこのplayer.mxmlに 動画プレイヤーの各機能を作っていきます。
一般的な動画再生サイトのplayerはカッコいい停止再生ボタンや、音量調節、再生ヘッド位置とか 色々表示されていますが、今回はUI的なことに凝ると本題から外れるので最低限の以下の機能&情報を 表示することにしましょう.
- 動画再生画面
- 中断/再生ボタン
- 読み込み済みbyte数 と Total byte数
- 再生の経過時間 と Total再生時間
です。
とりあえず上の情報を並べると、例えば
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
width="250" height="250">
<mx:Label text="my youtube player"/>
<mx:VideoDisplay id="vd" width="100%" height="100%" />
<mx:HBox>
<mx:Button label="play" />
<mx:Button label="stop" />
</mx:HBox>
<mx:HBox>
<mx:Label text="Loading Info:" />
<mx:Label id="byteloaded" />
<mx:Label text="/" />
<mx:Label id="bytetotal" />
</mx:HBox>
<mx:HBox>
<mx:Label text="Playing Info:" />
<mx:Label id="playtime" />
<mx:Label text="/" />
<mx:Label id="totaltime" />
</mx:HBox>
</mx:VBox>
という風になります。idは必要な箇所にすでに割り当てました.動画プレイヤー風になるように デザインビューなどをみてみて調節ください.
さて、このプレイヤーを本体 (youtube_player.mxml) に設置するにはどうすればいいでしょう.
説明するのより、見てもらった方が理解しやすいのでそのまま貼付けます
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:module="module.*" layout="vertical">
<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;
[Bindable]
public var movielist:ArrayCollection = new ArrayCollection;
public function send_request():void {
var uv:URLVariables = new URLVariables;
uv.vq = keyword.text;
youtubeapi.request = uv;
youtubeapi.send();
}
public function youtubeapi_result(event:ResultEvent):void {
movielist.removeAll();
for(var i:int=0;i<event.result.feed.entry.length;i++) {
movielist.addItem(event.result.feed.entry[i]);
}
}
public function playmovie():void {
var tmp:Array = movielist.getItemAt(tilelist.selectedIndex).id.split('/');
var video_id:String = tmp[tmp.length-1];
var uv:URLVariables = new URLVariables;
uv.video_id = video_id;
flvurlapi.request = uv;
flvurlapi.send();
}
private function flvurlapi_result(event:ResultEvent):void {
Alert.show(event.result.url);
}
]]>
</mx:Script>
<mx:ApplicationControlBar width="100%">
<mx:TextInput id="keyword" />
<mx:Button label="youtube search" click="send_request()"/>
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:TileList width="100%" height="100%" dataProvider="{movielist}" itemRenderer="movieitem" doubleClickEnabled="true" doubleClick="playmovie()" id="tilelist" />
<module:player id="flvplayer" />
</mx:HDividedBox>
<mx:HTTPService id="youtubeapi"
url="http://gdata.youtube.com/feeds/api/videos" method="GET"
result="youtubeapi_result(event)" />
<mx:HTTPService id="flvurlapi"
url="http://hiyuzawa.jpn.org/api/youtube.php" method="GET"
result="flvurlapi_result(event)" />
</mx:Application>
名前空間がどうこうという説明を本来するのでしょうが、こうやって上部におまじない書くと、そのフォルダ内のmxmlファイルを読み込むことができますよ。その際は通常 mx:hoge と書いている部分を module:hoge という風にするんですよ。と覚えておいてくださいさて、これで実行してみてください。基本のロジックは変えていませんが、一番最初に HDividedBox を設置してから右側に何も無かった部分にplayer.mxmlで定義したモジュールが加わったことでしょう.
後もう少しです。まずは、とっととダブルクリックで再生できるようにまずはしてしまいましょう. playerで定義した VideoDisplayのsourceに先ほどAPIで取得した flv のURLをセットすれば再生されます.
これをどのように実装するかは下記になります. Bindable で 変数 flvurl を定義しそれを VideoDisplayの sourceにセットする. こうすると youtube_player.mxml で先ほど定義した flvplayer から flvplayer.flvurl でアクセスできます.
player.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="250" height="250">
<mx:Script>
<![CDATA[
[Bindable]
public var flvurl:String = new String;
]]>
</mx:Script>
<mx:Label text="my youtube player" />
<mx:VideoDisplay id="vd" width="100%" height="100%" source="{flvurl}"/>
<mx:HBox>
<mx:Button label="play" />
<mx:Button label="stop" />
</mx:HBox>
<mx:HBox>
<mx:Label text="Loading Info:" />
<mx:Label id="byteloaded" />
<mx:Label text="/" />
<mx:Label id="bytetotal" />
</mx:HBox>
<mx:HBox>
<mx:Label text="Playing Info:" />
<mx:Label id="playtime" />
<mx:Label text="/" />
<mx:Label id="totaltime" />
</mx:HBox>
</mx:VBox>
youtube_player.xml の一部
private function flvurlapi_result(event:ResultEvent):void {
flvplayer.flvurl = event.result.url;
}
実行してみてください。 検索してサムネイルをダブルクリックすると動画がplayerで再生されます.実はこれで youtube_player.mxml は終わりです。playerの装飾は全部player.mxml の中で実装されます.
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="250" height="250" creationComplete="init()">
<mx:Script>
<![CDATA[
import mx.events.VideoEvent;
[Bindable]
public var flvurl:String = new String;
private function init():void {
vd.addEventListener(ProgressEvent.PROGRESS, function():void {
byteloaded.text = vd.bytesLoaded.toString();
bytetotal.text = vd.bytesTotal.toString();
playtime.text = vd.playheadTime.toString();
totaltime.text = vd.totalTime.toString();
});
vd.addEventListener(VideoEvent.PLAYHEAD_UPDATE, function():void {
byteloaded.text = vd.bytesLoaded.toString();
bytetotal.text = vd.bytesTotal.toString();
playtime.text = vd.playheadTime.toString();
totaltime.text = vd.totalTime.toString();
});
}
]]>
</mx:Script>
<mx:Label text="my youtube player" />
<mx:VideoDisplay id="vd" width="100%" height="100%" source="{flvurl}"/>
<mx:HBox>
<mx:Button label="play" click="vd.play()"/>
<mx:Button label="stop" click="vd.pause()"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Loading Info:" />
<mx:Label id="byteloaded" />
<mx:Label text="/" />
<mx:Label id="bytetotal" />
</mx:HBox>
<mx:HBox>
<mx:Label text="Playing Info:" />
<mx:Label id="playtime" />
<mx:Label text="/" />
<mx:Label id="totaltime" />
</mx:HBox>
</mx:VBox>
playとstop(pause)のボタンへの割当は上の要領でok. あとは 動画読み込み中、再生中に
各種データ(読み込みbyte, 再生時間の更新をするために, VideoDisplayの addEventListener の- ProgressEvent.PROGRESS = FLV ファイルが完全にダウンロードされるまで継続的に送出されます。
- VideoEvent.PLAYHEAD_= UPDATE ビデオの再生中に 0.25 秒ごとに送出されます
というイベントでUpdate通知させます. 各種情報は VideoDisplayのリファレンスから抜き出せばもっとリッチなplayerがつくれます.
さて、長々説明してきた Flex builder で作る youtubeが検索できるplayer付きアプリ もこれで完成しました。完成系は
こんな感じになったと思います.
かなり我流な感じもしますので、ちゃんとしたflexの参考書からみれば間違った解説している可能性が 多くある気がしますが、その辺はご了承ください.
それでは長々とお付き合い下さいましてありがとうございました。
昨年に引き続きことしも、先週 ツインリンクもてぎ に行ってきたよ。
毎度のことながらここはレースシーズン以外は空いててすごく良い!
多摩テックや鈴鹿と同様に子供向けのアトラクション施設とかあるから子供も大満足。
子供向けファミリープランとかあるからそれ利用しました。
子供も楽しんだんだけど、私も楽しみました。
工作教室で竹馬作ったり...

感激!! この時代に生きててよかった。
大げさだと言われるかもしれないが、それぐらい楽しい。

ただ、サーバが弱いのか1/3ぐらいの確率でエラーになってしまうのは
早く増強なりなんとかしてほしい。
今日は早く寝たかったのに...
今日は、お昼過ぎまでだらだら過ごし、3連休の中盤なのに、このままでは
イカン!(昨日は毎度の川崎ラゾーナにいっただけ。)ということで、
東京駅周辺に遊びにいきました。
東京駅は、エキナカGranStaが最近Open、
八重洲口の大丸がリニュアルなど、そんな影響でひと大杉。。
しかもおいしそうな店だらけ。朝からご飯食べてなくて、腹減った。。
で、結局 味の牛たん 喜助ってところで
牛タン食べた。うまかった。昼からカミサンと2人でビール。
その後、大丸とか見に行って、こちらも人多すぎて大変だったので、
有楽町まで散歩がてら歩いた。国際フォーラム奇麗でした。

ビックカメラにいっておもちゃコーナで暇つぶす。
うちの少年はサンタに何もらおうかと、ウロウロ。(ウフフ..)
さすがにクリスマス前ものすごい人、買うまですごい行列。。。
君たちそんな直前に買いにきて混むの当たり前じゃん!もっと前もって...

今日はキッザニアにいってきました。
なかなかチケットがとれないのだけどたまたま子供の友人から家族分チケットを譲ってもらいました。
子供とカミサンは何度か行ったことがあり僕だけが初めてだったのだけど
カナーリ面白かったです。
この施設自体は「子供が色々なお仕事を体験できる」をコンセプトに作られた
エデュテイメントタウンらしいのですが、その色々な職業は実際の大人社会の会社が協賛しているらしく
その種類と内容も本格的でしかも複数のお仕事がうまーく連携していたりして感激しました。。
たとえば、お金を払えば「運転免許センター」で免許をとる。それには健康診断が必要で
その診断は別の「お医者さん」という施設で先生役をしている人から診断を受ける。
「レンタカー」で車に乗ったら、「ガソリンスタンド」の施設で働く人から給油を受ける。
「いらっしゃいませ!!!!!」と小さい子が叫んでいるのがカワイイ。
「宅急便屋さん」は「ブティック」で働く人店員(これも子供)に集荷に訪れる。
それはもう ららぽーとの3Fで色んなことがおきてます(笑)
さて、うちの子は今日は何したかというと...
今日帰宅して早々。うちの子供が
「とおちゃーん!とおちゃんのために学校から本借りてきたよ!」
と、何事かと思ったら...

インターネットのひみつ - 学研 - 日本PTA全国評議会推薦図書でした. あまりにも懐かしい描写ばかりで感激しました!
「電話線をつないで接続完了!」とか書いてあります。その辺は多少時代を感じますが
マウスの操作からインターネットの仕組みまで結構ツボを押さえた良書です。
ヤフーとか画面相当古いバージョンで載ってます。 2000年前後かな...

今日は 8回目の結婚記念日でした。
毎年、式を挙げた教会の神父さんから当日にお便りがきます。
もう既に何千組もそこで式を挙げているのですが、
ちゃんと全組の記念日にコメントを添えてカードを送ってくれます。

毎年この時期になると思い出します。1999/12/10 我ながら良い式でした。
leopard を新しくインストールして、 環境を作ってなかったので改めて作った。
毎度少し悩むのでメモメモ...
1. 準備
Mac-Portを最新の状態にして
sudo port -d sync
2. apache2のインストール
設定ファイルを作って
sudo cp /opt/local/apache2/conf/httpd.conf.sample /opt/local/apache2/conf/httpd.conf
ちゃんと起動できるか確認して
sudo /opt/local/apache2/bin/apachectl start
http://localhost/
sudo /opt/local/apache2/bin/apachectl stop
httpd.confの
#LoadModule ssl_module modules/mod_ssl.so
コメントアウトが必要 (leopard 07/12現在)
3. MySQL5のインストール
sudo port install mysql +server
初期設定をして
sudo -u _mysql mysql_install_db5
# -u _mysql 忘れるとハマる. /opt/local/var/db/mysql5/*.err 確認
起動&接続確認して
sudo mysqld_safe5 &
mysql5 -u root
sudo mysqladmin5 shutdown
sudo vim /etc/my.cnf
4. PHP5のインストール
sudo port install php5 +apache2 +mysql5 +pear
apacheにPHPかまして
cd /opt/local/apache2/modules/
sudo /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.so
PHP設定ファイルつくって
cp /opt/local/etc/php.ini-dist /opt/local/etc/php.ini
httpd.conf に
Include conf/extras-conf/*.conf
追記する
5. 最後に確認
$ cat /opt/local/apache2/htdocs/phpinfo.php
<?php
phpinfo();
?>
http://localhost/phpinfo.php

