kmzwのブログ

コミック や ガジェット の話題が中心の日記です。

クマでもできるchumby入門!<Widgetを作るの巻>

chumbyをしゃぶり尽くすなら,自由にWidgetが作れるんだから作らにゃいかん.と言うわけで,今回は以前紹介したゆっくりしていってね!」のWidgetが出来るまでお届け.↓これ.
  D
ところで,公式の[Japanese]カテゴリに[yukkuri siteittene!]のWidgetがいつの間にか登録されてます.パクられた!(※冗談です.真に受ける人がいるからいつも困る) やっぱり東方って人気なんだなぁ.そういえば同僚のIOSYSメンバにサイン入りCDねだってんだけど,恥ずかしがってくれない・・・.

書き始めたものの,お腹空いたのでちょっと外出.続きは帰ってからっと.
と,書きつつ続き書かずに寝てしまったorz.再開.

開発環境を選ぶ

まず,Widgetの作成にどんな環境を使うか選ばなくてはいけません.Wikiによれば,ChumbyWidgetは,言語としてはActionscript2でFlash8ベースのFlashLite3.0によって作成するようです.
Flash作成と言えば初めに思い浮かぶのがMicromediaAdobe Flashです.今手に入るのはADOBE FLASH CS4 PREOFESSIONALのようですが,8万円はハードルが高いです.少なくとも薄給サラリーマンの私にはポンと出せません.
では,サードパーティの製品はどうかというと,ざっと検索してみたところ1万円前後の製品がいくつかあるようです.MotionMakerや,FlaaveFreeMotionWeb Effectなどです.MotionMakerは,簡単操作でFlashが作成できスクリプトも必要ない(使用できない)のが特徴のようです.Flaaveも,同様に簡単にFlashが作成できWin/Macに両対応だそうです.FreeMotionは,Flashの収集・解析機能とスクリプトの編集が可能.Web Effectは,安いです.FreeMotionあたりを気が向いたら体験版試してみようかな.
フリーの環境も調べてみると,国産のオーサリング環境でParaFla!suzukaと言うのが有名なようです.機能的には詳しく見ていないので比較できませんが,ParaFla!スクリプトを使ってバリバリ開発できそうですが,タイムラインがないのでアニメーション的なFlashsuzukaのほうがよさそうです.とりあえずsuzukaをインストールしてみました.ITproの記事が参考になりそうなので,ここを見て試してみようと思います.
ChumbyWikiの開発環境の項目を見てみると,FlashDevelopが薦められています.WikiにはFlashDevelopのサンプルやテンプレートが公開されているので,どうやらコレを使うのがよさそうです(先にWiki見ればよかったorz).FlashDevelopは,フリーのActionscript2コンパイラであるMTASC用のIDEであるようです.FlexSDK3と併用すればActionscript3の開発もいける優れもの.というわけで,FlashDevelopを使ってWidgetの作成をしようと思います.

開発環境を整える

さっそく,FlashDevelopをインストールするわけですが,FlashDevelopには「Microsoft.NET Framework Version 2.0 再頒布可能パッケージ」が必要ですので,先にリンク先からダウンロードしてインストールします.インストールは[次へ]をポチポチ押していけば完了します.
次はいよいよ本命FlashDevelopです.リリースページからダウンロードします.私は「3.0.0 Beta9」をインストールしました.これも[NEXT]をポチポチ押していけば完了.
  
最後にChumbyWikiにあるテンプレートをインストールします.先人の知恵を活用させてもらわない手はありません.ChambyWikiのFlashDevelopのページからChumbyDevelop.zipをダウンロードします.このページにはサンプルがいくつかあり,とても参考になるので見てみることをお勧めします.ダウンロードしたファイルを展開すると,テンプレートとサンプルが入ってます.「05 Chumby Project」というフォルダがテンプレートなので,こいつをFlashDevelopのテンプレートフォルダにコピーします.私の場合,フォルダ名を「260 ActionScript 2 - Chumby Project」に変更して,「C:\Documents and Settings\[ユーザー名]\Local Settings\Application Data\FlashDevelop\Templates\ProjectTemplates」にコピーしました.
  
以上で,開発環境が整いました.最後の最後におまけですが,私の環境ではSWFファイルを実行すると動画プレイヤが起動するように関連付けされてしまっているので,ちょっとうっとおしいです.そこで,AdobeのサイトここからSWF専用のアプリケーション「Windows Flash Player 9 プロジェクタコンテンツデバッガ」をダウンロードして,右クリックでSWFを再生できるようにしました.FlashDvelopには専用のプレイヤがあるので,必須ではありませんが必要な方はご参考まで.ちなみに,ダウンロードしたファイルはインストールファイルではなくプレイヤ本体です(実行して初めキョトンとしましたw).

素材を揃える

次はFlash用の素材を作ります.今回は突っつくと「ゆっくりしていってね!」としゃべるFlashを作るので絵と音声が必要です.
まずは,ゆっくりしていってね!のあの絵です.あの絵はまそ氏イラストが元であるようです.さっそく自分なりに簡略化して必要な絵を描きます.30分ほどで完成.線がヨレヨレですが気にしない!
  
コレを小さくして,起動画像を作成.
  
次に,chumbyに表示して動かすところを決めます.
  
あとは,動かす部分を数枚やっつけました.
      
これで画像がそろいました.

次に,音声です.上記の動画ではコエラボのC.C.(略称?)というキャラクターの音声を使わせていただきましたが,個人で使うのは良いけど再配布してはいけないようです.と言うわけで,今回は「AquesTalk」を利用させてもらいます.AquesTalk Win版をダウンロードして,同梱されているサンプルアプリケーションで「ゆっくりしていってね!」の音声を作成しました.音声記号列仕様を見つつ適当に作成します.
  
で出来たのがコレ→ykr2.mp3

※追記
メールでご指摘もらいました.ありがとうございます.
一つは,「AquesTalkでmp3作成できません」というもので,すみません説明不足でした.AquesTalkはWAVファイルしか吐けませんので,別途エンコーダでmp3に変換してください.変換する方法は他に分かりやすい説明をされている方がたくさんいますので,Google先生に聞いてみてください.ちなみに私が普段使っているのは,BonkEncです.海外製ですが初起動時に日本語を選べるようになってます.
もう一つは,「上のmp3がchumbyでうまく再生できません」と言うもので,私も試してみたところ確かに変です.周波数やビットレートを変えて試してみたところ,どうやらモノラルなのがいけないようです.通常エンコーダーでモノラルからステレオに変換できないので(逆は出来ますが),AquesTalkで作成したWAVファイルをSoundEngineでステレオ化した後,エンコードしたものに差し替えたところきちんと再生できました.
  
上記のファイルも差し替えておきました.
ちなみに,ご質問などはコメントでいただけると助かります.

これで,全ての素材がそろいました.

コードを書く

いよいよ,コードを書きます.
まず,FlashDevelopを立ち上げてメニューの[Project]-[New Project]を選択します.表示されたダイアログで,Chumbyのテンプレートを選択し,名前[Name]と保存場所[Location]を指定して[OK]します.
  
次に,指定した保存場所にプロジェクトファイル(*.fdp)や「classes」と「library」といったフォルダが作成されているので,「library」フォルダに先ほど作成した画像や音声をコピーすると以下のような状態になると思います.
  
メインのスクリプトは,「ChumbyApp.as」のようです.右側にあるリストの「ChumbyApp.as」をダブルクリックすると,ソースが表示されます.とりあえず何も考えずにコンパイルしてみましょう.ツールバーの青い三角をクリックすると,コンパイルされて,SWFファイルが生成され実行されます.ブルーバックに文字列表示と言う単純なSWFですね.ところで,冷静に考えるとスクリプトなのにコンパイルが必要なのは違和感を感じるのが私だけでしょうか・・・.
  
ここからは,この「ChumbyApp.as」を編集して目指すSWFを作っていくわけですが,私はActionscriptなんてさっぱり分かりません.ChambyWikiのFlashDevelopのページのサンプルを参考にしつつ,Adobeのリファレンスの「ActionScript 2.0 Language Reference」あたりを見つつ見よう見まねで書いてみました.プログラムなんてものは習うより慣れろの最たるもので,いきなり何か作ろうとしたほうが早く覚えることができると思っているので,いつもいきなり何か作り始めるんですが我流なのでたいてい後で困りますw.と言うわけで,以下に「ChumbyApp.as」のソースを示しますが参考にはしないでください.

/*
 * Simple Chumby Application
 */
class ChumbyApp
{
	private var parent:MovieClip;
	private var menu:Menu;
	private var time_id:Number;
	private var sleep_cnt:Number;

	function ChumbyApp(mc:MovieClip)
	{
		// save reference to main movieclip
		this.parent = mc;

		// set background and app title
		// Util.mainScreen(mc, 320, 240, Util.BLUE_1, "My First Chumby Application");

		mc.createEmptyMovieClip("ykr13_mc",  mc.getNextHighestDepth());
		mc.ykr13_mc.loadMovie("library/ykr13.jpg");
		mc.createEmptyMovieClip("ykr12_mc",  mc.getNextHighestDepth());
		mc.ykr12_mc.loadMovie("library/ykr12.jpg");
		mc.createEmptyMovieClip("ykr11_mc",  mc.getNextHighestDepth());
		mc.ykr11_mc.loadMovie("library/ykr11.jpg");
		mc.createEmptyMovieClip("ykr02_mc",  mc.getNextHighestDepth());
		mc.ykr02_mc.loadMovie("library/ykr02.jpg");
		mc.createEmptyMovieClip("ykr01_mc",  mc.getNextHighestDepth());
		mc.ykr01_mc.loadMovie("library/ykr01.jpg");
		mc.createEmptyMovieClip("ykr_mc",  mc.getNextHighestDepth());
		mc.ykr_mc.loadMovie("library/ykr.jpg");
		var ykr_sound:Sound = new Sound();
		ykr_sound.loadSound("library/ykr2.mp3");
		
		mc.sleep_cnt = 0;
		this.time_id = setInterval(this.sleep, 150, mc);

		mc.onMouseDown = function() 
		{
			ykr_sound.stop();
			ykr_sound.start();
			this.sleep_cnt = 200;
		}
	}
	
	function sleep(mc:MovieClip)
	{
		//trace("sleep_cnt:" + mc.sleep_cnt);

		if (mc.sleep_cnt == 15) 
		{
			mc.ykr11_mc.swapDepths(mc.getNextHighestDepth()-1);
			mc.sleep_cnt = 100;
		}
		else if (mc.sleep_cnt == 110)
		{
			mc.ykr12_mc.swapDepths(mc.getNextHighestDepth()-1);
		}
		else if (mc.sleep_cnt == 120)
		{
			mc.ykr13_mc.swapDepths(mc.getNextHighestDepth()-1);
		}
		else if (mc.sleep_cnt == 130)
		{
			mc.ykr12_mc.swapDepths(mc.getNextHighestDepth()-1);
		}
		else if (mc.sleep_cnt == 131)
		{
			mc.ykr11_mc.swapDepths(mc.getNextHighestDepth()-1);
			mc.sleep_cnt = 100;			
		}
		else if (200 <= mc.sleep_cnt && mc.sleep_cnt < 207 && mc.sleep_cnt % 2 == 0)
		{
			mc.ykr01_mc.swapDepths(mc.getNextHighestDepth() - 1);
		}
		else if (200 <= mc.sleep_cnt && mc.sleep_cnt < 207 && mc.sleep_cnt % 2 == 1)
		{
			mc.ykr02_mc.swapDepths(mc.getNextHighestDepth()-1);
		}
		else if (mc.sleep_cnt == 207)
		{
			mc.ykr01_mc.swapDepths(mc.getNextHighestDepth()-1);
		}
		else if (230 <= mc.sleep_cnt)
		{
			mc.ykr11_mc.swapDepths(mc.getNextHighestDepth()-1);
			mc.sleep_cnt = 100;			
		}

		mc.sleep_cnt++;
	}

	static function main(mc:MovieClip)
	{
		var app = new ChumbyApp(mc);
	}
}

以上のように編集しました.詳しい説明はしませんが,画像や音声を読み込んで,タイマー設定して順番に画像を表示しているだけです.動けばいいんですw.コンパイル&実行すると無事SWFが作成できました.
  
ちなみに,Adobeのリファレンスサイトが重いので,手元にActionscriptの本が欲しいと思って本屋に行きましたが,売っているのはActionscript3ばかりでした.しかも,ほとんどがAdobeFlash前提となっています.Actionscript2を対象としていて,AdobeFlashが強調されていないのは↓ぐらいでした.

chumbyで実行する

さて,最後に作成したSWFをchumbyで実行してみましょう.
Widgetを実行するには2つの方法があります.チャンネル登録して実行する方法と,ssh経由でコマンド実行する方法です.

チャンネル登録して実行する方法

まず,チャンネルに登録してWidgetを実行する方法です.おそらく,こちらが正攻法だと思います.まず,テキストエディタで「profile.xml」と言うファイルを作成します.内容は大体以下のとおりです.

<profile>
	<widget_instances>
		<widget_instance id="1">
			<widget>
				<name>Tsun Tsun Widget</name>
				<description>Yukkuri Shiteittene !!</description>
				<version>1.0</version>
				<mode time="120" mode="timeout" />
				<access sendable="false" deleteable="false" access="private" virtualable="false" />
				<user username="myusername" />
				<thumbnail href="file:////mnt/usb/ykr_thumb.jpg" contenttype="image/jpeg" />
				<movie href="file:////mnt/usb/ykr.swf" contenttype="application/x-shockwave-flash" />
			</widget>
			<access access="private" />
			<mode time="120" mode="timeout" />
			<widget_parameters>
				<widget_parameter>
					<name>nickname</name>
					<value>kmzw</value>
				</widget_parameter>
				<widget_parameter>
					<name>mail</name>
					<value>tsmt@kmzw.jp</value>
				</widget_parameter>
			</widget_parameters>
		</widget_instance>
	</widget_instances>
</profile>

上記をベースに,タグにWidget名を,タグに詳細説明を,タグのhrefにサムネイル画像を指定,タグのhrefにWidgetを指定,と言ったようにご自身のWidgetに合わせて書き換えてください.
次に,サムネイル画像を用意します.実はなくても良いようなのですがせっかくなので用意します.
  
画像サイズは80x60です.大きすぎると全て表示されませんのでご注意を.
「profile.xml」ファイルとサムネイル画像を,作成したWidgetと一緒にUSBメモリのルートに保存します.めんどくさいので余計なファイルも入ってますw.必要なのは,「ykr.swf」と「ykr_thumb.jpg」,「profile.xml」,「library」ディレクトリですね.
  
そして,chumbyの電源をいったん落とし,Widgetを保存したUSBメモリをchumbyに刺した後chumbyの電源を入れると,チャンネルに作成したWidgetが追加され,無事再生!
  

ssh経由でコマンド実行する方法

こっちは,chumbyにアクセスしてシェル上でコマンドから実行する方法です.こちらは,Flash作成時に動作を確認するなどの用途で使うと良いと思います.
アクセスするためには,sshに対応したターミナルクライアントが必要ですので,予めインストールしておいてください.有名どころだと,Tera Termとか,PuTTY(日本語版)でしょうか.私はPoderozaを使っています.FlashDevelopと同様に「Microsoft.NET Framework Version 2.0 再頒布可能パッケージ」が必要ですが,インストールがらくちんなので気に入ってます.
chumbyに接続するためには,SSHのデーモンを立ち上げる必要があります.手順は,「細かい設定をするの巻」のエントリーの「chumbyのスクリーンショットを保存する」手順と同じです.[コントロールパネル]-[設定]-[Chumby情報]を表示すると↓が表示されます.ここで表示されているchumbyのIPアドレス(下から4行目の「ip」の値)を覚えておいてください.
  
次に,左上の「π」の記号をクリックすると,↓のような裏メニューが表示されます.
  
[SSHD]と言うのをポチッと押してください.不細工タコが表示されてSSHDデーモンが立ち上がります.
次に,PCからchumbyにログインします.ターミナルクライアントはPoderozaを前提にします.新規TELNET/SSH接続ダイアログから以下の設定で接続しましょう.

  • ホスト:chumbyのIPアドレス
  • プロトコル:SSH2
  • ポート:SSH(22)
  • アカウント:root
  • 認証方式:パスワード
  • パスフレーズ:[空]

  
初回アクセス時には確認ダイアログ後に以下のようなログイン画面が表示されてchumbyにログオンできます.
  
busyboxなんですね.せっかくなので,chumbyくんを赤裸々に見てみましょう.

chumby:~# uname -a    
Linux (none) 2.6.16-csb #1 Thu Jul 24 11:14:11 PDT 2008 armv5tejl unknown

カーネルは2.6.

chumby:~# cat /proc/cpuinfo 
Processor       : ARM926EJ-Sid(wb) rev 4 (v5l)
BogoMIPS        : 174.89
Features        : swp half thumb fastmult edsp java 
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant     : 0x0
CPU part        : 0x926
CPU revision    : 4
Cache type      : write-back
Cache clean     : cp15 c7 ops
Cache lockdown  : format C
Cache format    : Harvard
I size          : 16384
I assoc         : 4
I line length   : 32
I sets          : 128
D size          : 16384
D assoc         : 4
D line length   : 32
D sets          : 128

Hardware        : Freescale MX21ADS
Revision        : 0000
Serial          : 0000000000000000

おぉ,Freescaleだ.

chumby:~# cat /proc/meminfo 
MemTotal:        61928 kB
MemFree:         13520 kB
Buffers:          7120 kB
Cached:          15972 kB
SwapCached:          0 kB
Active:          27996 kB
Inactive:        11008 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:        61928 kB
LowFree:         13520 kB
SwapTotal:           0 kB
SwapFree:            0 kB
Dirty:               0 kB
Writeback:           0 kB
Mapped:          21072 kB
Slab:             4360 kB
CommitLimit:     30964 kB
Committed_AS:    78700 kB
PageTables:        376 kB
VmallocTotal:   188416 kB
VmallocUsed:       420 kB
VmallocChunk:   187996 kB

メモリは64MBで,空きは14MBぐらい.

chumby:~# df -h 
Filesystem                Size      Used Available Use% Mounted on
/dev/mtdblock5           33.0M     33.0M         0 100% /
none                     30.2M      4.0k     30.2M   0% /dev
none                     32.0M    552.0k     31.5M   2% /tmp
none                     32.0M     60.0k     31.9M   0% /var
none                     32.0M         0     32.0M   0% /mnt
/dev/mtdblock1            2.0M      1.6M    436.0k  79% /psp

なんということでしょう.日本語化したらディスクの空きがたった436kBにw.

chumby:~# ps
  PID  Uid        RSS    VSZ Stat Command
    1 root        332   1656 SW  init       
    2 root                   SWN [ksoftirqd/0]
    3 root                   SW  [watchdog/0]
    4 root                   SW< [events/0]
    5 root                   SW< [khelper]
    6 root                   SW< [kthread]
   14 root                   SW< [kblockd/0]
   17 root                   SW< [khubd]
   59 root                   SW  [pdflush]
   60 root                   SW  [pdflush]
   62 root                   SW< [aio/0]
   61 root                   SW  [kswapd0]
  679 root                   SW  [mtdblockd]
  680 root                   SW  [ftld]
  681 root                   SW  [nftld]
  975 root                   SWN [jffs2_gcd_mtd1]
  983 root        332   1856 SW  /sbin/syslogd -C200 
  990 root        512   1588 SW< /sbin/udevd --daemon 
 1001 root        764   3164 SW  mountmon --daemon 
 1266 root        584   1512 SWN headphone_mgr 
 1440 root                   DW  [rt73]
 1441 root                   DW  [rt73]
 1635 root        104   1660 SW  udhcpc -t 5 -n -p /var/run/udhcpc.rausb0.pid -i rausb0 
 1722 root         88   1656 SW  /usr/sbin/httpd -h /www 
 1739 root       1316  11440 SW  mDNSResponder 
 1772 root        656   2724 SW  mDNSPublish kumap_black _http._tcp 80 
 1787 root       1312  20808 SW  chumbhowld 
 1799 root        796   4144 SW  /usr/sbin/crond -c /etc/cron/crontabs 
 1807 root        400   3268 SW< /bin/chumbalarmd 
 1810 root        120   1656 SW  init       
 2090 root        832   2876 SW  /sbin/sshd 
 2113 root        656   2724 SW  mDNSPublish kumap_black _ssh._tcp 22 
 2162 root        380   1660 SW  /bin/sh /usr/chumby/scripts/start_control_panel 
 2216 root       1924   5076 SW  /usr/sbin/btplayd 
 2217 root      15624  35656 SW  /usr/bin/chumbyflashplayer.x -i /tmp/controlpanel.swf 
 2218 root        292   1656 SW  sh -c chumbpipe  /tmp/.fpcmdsend /tmp/.fpcmdrecv 
 2219 root       1040   3000 SW  chumbpipe /tmp/.fpcmdsend /tmp/.fpcmdrecv 
 2221 root       3612   8608 SW  /usr/bin/chumbyflashplayer.x -i /tmp/controlpanel.swf 
 2581 root       1476   5508 SW  sshd: root@pts/0
 2585 root        952   4152 SW  -sh 
 3470 root        816   4148 RW  ps 

脱線しました.戻りましょう.
次に,作成したSWFを保存したUSBメモリをchumbyに刺します.「チャンネル登録して再生する方法」のように「profile.xml」やサムネイル画像を用意する必要はありません.自動的にマウントされます.中身は以下のとおり.

chumby:~# ls -la /mnt/usb
drwxrwxrwx    5 root     root        16384 Jan  1  1970 .
drwxrwxrwt   12 root     root          240 Jan 30 07:10 ..
drwxrwxrwx    2 root     root        32768 Jan 28 15:23 library
-rwxrwxrwx    1 root     root         7800 Jan 27 15:37 ykr.swf

次に,コントロールパネルを停止します.

chumby:~# stop_control_panel 
*** stopping control panel
*** killing registered flashplayer pid: 2217
Adobe FlashLite 3.0.4 Release (Version 8,1,55,0)- Chumby Industries (version 7 build 85-733 [GCC 4.1.2   Microcross GNU X-Tools(tm)])
Built for: ironforge; Features: Video ALSA DMA ARM-optimizations
Build time: Thu 17Jul2008 1235
2009-01-30 07:19:41 ClientSettings::LoadCustomFont(/psp/fontmovie.swf) loaded successfully, 1461506 bytes
2009-01-30 07:19:41 Using code page 12
chumbyflashplayer.x: sending signal 15 (SIGTERM) to running instance 2217
2009-01-30 07:19:42 GetRegisteredInstancePid(/var/run/chumbyflashplayer.pid) open failed, errno = 2 (No such file or directory)
chumbyflashplayer.x: registered instance 2217 appears to have terminated
btplay client v1.3.1.32.38
Connected to btplayd instance 2216
Got response: OK 1010 flashplayer exit
OK 100 quit
Ignoring mismatched response 1010, expected 100
Warning: ignoring failed fetch, --no-failsafe specified!
Waiting 500ms for process to terminate
Continuing...
*** killing btplayd (SIGTERM): 4380
*** killing btplayd (SIGTERM): 2216
*** killing btplayd (SIGKILL): 4380
*** killing btplayd (SIGKILL): 2216
/usr/chumby/scripts/stop_control_panel: Flash player still running: 0

これで,chumbyが突いても操作できなくなります.そして,いよいよFlashの実行です.ルートディレクトリに移動後に実行します.(画像などの外部ファイルがルートからのパスで読み込まれる.なんででしょ?)

chumby:~# cd /
chumby:/# chumbyflashplayer.x -i /mnt/usb/ykr.swf 
Adobe FlashLite 3.0.4 Release (Version 8,1,55,0)- Chumby Industries (version 7 build 85-733 [GCC 4.1.2   Microcross GNU X-Tools(tm)])
〜省略〜

無事実行完了! Flashを止める時は[Ctrl+C]です.動作を確認したらchumbyを通常動作に戻しましょう.

chumby:/# start_control_panel

で,通常動作します.
実際には,

  1. USBメモリを刺す.
  2. 実行して動作確認する(# chumbyflashplayer.x -i /mnt/usb/hoge.swf )
  3. USBメモリを抜く(# umount /usb/mnt)
  4. Flashを更新してUSBメモリに保存.

を繰り返して使うかんじですね.

以上,長かった・・・