2011年11月9日水曜日

Nylon WebWorkersについて

WebWorkers

HTML5で導入されたWebWorkersは,JavaScriptで書かれたプログラムをバックグラウンドで動作させるAPIです.これがまたシンプルなAPIで,(1)Worker(バックグラウンドで動作するプログラム)を起動する,(2)Workerにメッセージを送る(postMessageメソッド),(3)Workerからメッセージが届いた際に実行する処理を記述する(onmessageやaddEventListener)のみでWorkerを制御します.メッセージがほとんど行き交わないような単純な処理であれば混乱は少ないのですが,メッセージが行き交うような処理になると,届いたメッセージの内容を元に処理を分岐させるなどの記述が多くなり,プログラム全体の見通しが悪くなります.

この問題点に対応したフレームワークとして,すでにAlexServiceが公開されています.(リリース記事:HTML5 Web Workersを超簡単に使えるようにするAlexService0.5を公開)一方,我々の開発しているNylonをWebWorkersに対応させたモジュールが「Nylon WebWorkers」です.

Nylon WebWorkers

Nylon WebWorkersはメイン側のモジュール「nylon.webworkers.js」とバックグラウンド側のモジュール「nylon.webworkers.client.js」から構成されたシンプルなモジュールです.これらのモジュールを使うと,Nylonの流儀に従って「キーワードに対する処理の記述」と「キーワード付きのメッセージ送信」のみによるモジュール間通信が可能になります.もちろん,nylon.coe.jsを併用した上でキーワードとして「server」を指定すればNylonサーバまでメッセージが届きますし,「broadcast」を指定すればNylonサーバを経由して,同時に接続されているWebブラウザ上のNylonモジュールまでメッセージが届きます.Nylonを通じてWorkerと通信するために必要なことはWorkerとして動作させるJSファイルを指定するだけです.以下に例を示します.

この記述だけで,worker.jsが読み込まれてバックグラウンドで実行され,キーワードベースの通信が可能になります.後はnylon.client.createで作成したオブジェクトにonメソッドでキーワードに対する処理を記述したり,emitメソッドでメッセージを送るのみです.

それでは,実際のプログラムを見てみましょう.今回のプログラムは,こちらのページに掲載されている,1から指定された数値までの和を計算するプログラムを改造したものです.

用意するファイルは以下のとおりです
worker_test.html・・・HTMLファイル
nylon.client.js・・・Nylon本体
nylon.webworkers.js・・・WebWorkersとやりとりするクラス
worker.js・・・わざわざWebWorkersを使うまでもありませんが,合計値を計算するプログラム
nylon.webworkers.client.js・・・ワーカ側のライブラリ(クラス化とか面倒なことはしていません)

以下に示すファイルはworker_test.htmlです.9〜11行目は「worker_set」を受け取った際の処理で,無事にWorkerと接続された場合に画面上に「connect」と表示しています.12〜14行目は「result」により計算結果を受け取り,アラートを表示します.18〜22行目はボタンがクリックされた際に「worker」と共に計算範囲をWorkerに渡します.16行目は,「worker.js」を読み込む処理です

続いて,以下に示すファイルは,Workerとして動作する「worker.js」です.4〜9行目はキーワード「worker」が届いた場合の処理です.具体的には入力された数値までの数値を足して,その結果を「result」で送っています.

11行目は「worker_set」を送っています.必須ではありませんが,通信できる状態になったことをメイン側に示します.

13行目はWorkerが受け取るキーワードをメイン側Nylonに送ってキーワード登録を行います.この処理が無いとWorker側にメッセージが届かないので重要なのですが,onメソッドに含める方がスマートなので近い内に削ります.(たぶん)

このように,onとemitのみでメイン側とWorker側の通信を記述できるので,通信が煩雑になっても混乱しなくてすみますし,通信するモジュールを限定しないので,様々なモジュールと組み合わせることが可能となります.今のところ,MeSHで使用するシミュレータ教材はSilverlight,Java,Flashを想定していますが,将来的にCPU速度が向上しJavaScriptでシミュレータ教材を記述できるようになった際には,Nylon WebWorkersを利用していこうと考えています.

動かし方

HTMLファイルをWebブラウザに放り込むと,URLの先頭が「file://」となります.この状態ではWebWorkersは使えません.必ずHTTP経由でアクセスしてください.今回の例ではすべての通信はクライアント内で完結しているのでNylonサーバは不要です.

HTTP経由で読み込むと,即座に画面上の「not connect」が「connect」に変わるはずです.この状態で入力欄に数値を入力してください.10や100ではすぐに結果が表示されてしまうので,もっと大きな数値が良いです.具体的な数値はCPUと相談して決めた上,お試しください. このエントリーをはてなブックマークに追加

2011年10月30日日曜日

Nylonサーバについて

Nylonサーバの役割

Nylonサーバは,あるWebブラウザから送られてきた通信内容を解析して,キーワードに「broadcast」が含まれていた場合には他のWebブラウザに転送する機能と,その他特定のキーワードに対応した処理を行う機能を持つものです.

理論上,言語は問いませんが,Socket.IOが便利なのでJavaScriptで記述するのが自然だと思います.実際,クライアント側の通信モジュール「nylon.coe.js」がSocket.ioを前提として組んでいます.

Nylonサーバのソースコード

以下にNylonサーバのソースコードを示します.できるだけコメントを付けているので,コメントを追いかけていけばなんとなく動作がわかると思います.21行目から31行目がメインの処理(=キーワードの解析・通信内容の転送など)となります.

動かし方

必要なものは,基本的にnode.jsとSocket.IOです.執筆時に使用したバージョンは,node.js 0.4.12とSocket.IO 0.8.5です.他にもexpressやejs(使っていますが,他のテンプレートエンジンでも構いません)も使用しています.

node.jsをインストールしたらディレクトリを作成して,上記プログラム(仮にnylon_server.js)をそのディレクトリに置きます.そのディレクトリの下にpublicディレクトリを作成し,前回紹介したプログラムを置いてください.ディレクトリの作成はexpressの機能を使ってもかまいません.

これで準備は整いました.後はWebブラウザからアクセスするだけで,リアルタイムチャットが動作します.複数のブラウザからアクセスして,動作を体験していただければ幸いです.なお,過去の書き込みの保存などは一切行なっておりません.リロードすると全書き込みがリセットされます.過去の書き込みの保存などを行いたい場合には,上記プログラムの29行目などに処理を追加することで対応可能です.追加するプログラムの例や,追加分のモジュール化などについては,そのうち紹介する予定です.

このエントリーをはてなブックマークに追加

2011年10月28日金曜日

Nylon入門

Nylonによるイベント送受信の流れ

前回はNylonの書き方について簡単に紹介しました.今回は,Webブラウザ間のやりとりについて,実際のコードを踏まえて説明したいと思います.下図のように,nylonサーバに複数のクライアント(Webブラウザ)が接続している状態です.ここで,obj_aは任意のオブジェクトです.COeはnylonサーバと通信するnylonモジュールで,正式なファイル名はnylon.coe.jsです.

Nylonのモジュールは,キーワードに従ってイベントを待つことができます.COeは,「broadcast」と「server」と言うキーワードで待ち受けをして,イベントの内容をnylonサーバに送ります.nylonサーバではキーワードを判別し,「broadcast」だった場合には,送られてきたイベントの内容を他のWebブラウザに送ります.「server」だった場合にはnylonサーバで何らかの処理を行います.続いて,各WebブラウザのCOeは送られてきたイベントを受け取り,ブラウザ内の他のオブジェクトにemitします.

例:リアルタイムチャット

リアルタイムチャットを例にとって説明します.リアルタイムチャットのオブジェクトがobj_aだと思ってください.obj_aはキーワード「append」に反応して書き込み欄に新たな内容を追加し,キーワード「clear」に反応して書き込み欄を消去するものとします.あるブラウザで発言があった場合,obj_aから「broadcast」と「append」という2つのキーワードを持ったイベントを送信します.擬似コードは以下のようになります.

イベントの登録

イベントの送信

実際のコード

リアルタイムチャットの実際のコードは以下のようになります.

6行目から8行目は,必要となるライブラリの読み込みです.サーバとの通信にはSocket.ioを使用しています.nylonサーバのプログラムは後日説明予定です.

22行目から32行目はイベントの登録です.先に説明したとおり,「append」と「clear」と言う2つのキーワードについて,その動作を登録しています

35行目から49行目はイベントの送信処理です.送信ボタンが押されたら名前と発言欄の内容を入れた,キーワード「append|broadcast」のイベントをemit(送信)しつつ,書き込み欄に追加します.

52行目から54行目は,接続した旨を表示するための確認欄の記述です.このプログラムではページ上部の「未接続」が「接続」に変化します.この辺は,格好良いインジケータを配置したいところですね.

その他

書き忘れていましたが,このソースプログラム及びNylonとNylonモジュールは無保証です.動作確認はChrome15.0.874.106,Safari5.1,Firefox7.0.1,iOS5のSafariで行っています

このエントリーをはてなブックマークに追加

2011年10月22日土曜日

Nylon

Nylonとは何か?

MeSHの開発に当たり,すべての機能を盛り込んだシステムとして開発すると,その後の変更作業が地獄と化すことが分かっています.そこで,e-Learningシステムを,個々の機能ごとに分割して開発し,統合する仕組みが必要となりました.その際,単にiframeなどで統合するのではなく,個別の機能を融合しつつ統合する仕組みが望まれました.今回は,その仕組として開発されたNylonについて説明します.

具体的に何が困るのか?

MeSHで目指しているWebによるリアルタイムe-Learningを実現することは,node.jsとsocket.ioのおかげで用意になりました.しかし,全ての機能を盛り込んだシステム(=モノリシックなシステム)を開発すると,機能追加や変更が面倒です.どこにバグが潜んでいるかヒヤヒヤです.

では,リアルタイムe-Learningを実現する機能をバラバラに見ていきましょう.まずは,スライド表示位があります.スライドを表示すると,そこにペンで書き込みしたくなります.そうすると,説明している姿を動画に残して,その動画に合わせてスライドやペンを再現したくなります.または,学生のペンによる書き込みを残しておくとか,「重要」などのマーキングもしたくなります.さらに,シミュレータについてもリアルタイムで操作情報を配信したり,後の自学自習に生かしたくなります.

これらの機能を融合しつつ統合することはできないでしょうか?そこで生まれたのがNylonという考え方です.具体的には,様々なモジュール単位で開発を行いつつ,モジュール間の動作を制御するイベント情報をやり取りするフレームワークです.

EventEmitter

ベースとなるヒントは,node.jsのソースコードに隠されていました.それを発見したのは当時学生だったi君です.どの様な仕組みかと言うと,個々のオブジェクト毎にキーワードとコールバック関数を定義する仕組みです.これにより,イベント駆動型のサーバ記述を実現しています.この仕組はEventEmitterと名付けられています.

EventEmitterをベースに,Webブラウザ上で動作する複数のモジュール間の通信を,共通するイベントマップで制御して,モジュール同士の「ゆるい」結合を実現したのがNylonです.Nylonとは,i君いわく,mesh(網目の織物)を実現するための素材から連想したとのことです.筆者は「モジュール同士を紡ぐ人工的な素材」と再定義しています.
ここで言うモジュールですが,Webブラウザ上で動作するモジュール + Webサーバサイドのモジュール + WebWorkersのモジュール + iframeに読み込まれたモジュール + Webサーバを通じて別のWebブラウザ上で動作するモジュールなどを含みます.

つまり,これまで面倒だった,Webブラウザ間の通信や,WebWorkersのworker側とメイン側の通信などを統一的に扱うことを可能とするフレームワークです.

Nylonの動作イメージ

obj_a, obj_b, guiの3つのオブジェクトがあり,これらが協調動作する様子を簡単に説明します.guiは,Webブラウザ上のボタンなどから制御されるオブジェクトと仮定します.obj_aはイベントとして,"A"を受け取り何らかの処理を行います.同様にobj_bはイベントとして,"B"を受け取り何らかの処理を行います.guiはAボタンが押されたらイベント"A"を送信します.同様にBボタンが押されたらイベント"B"を送信します.さらにCボタンが押されたらイベント"A"とイベント"B"を送信します.(プログラム中では"A|B"と表記)これらの動作を図にすると以下のようになります.
このように,キーワードをイベントとして送受信し合う仕組みがNylonです.この,「キーワードだけで動作する」というゆるい仕組みなので,モジュールのアップデートにも柔軟に対応できます.

Nylonの動作範囲と実際のプログラミング

先の例では,Webブラウザ内のモジュールを連想しますが,実際にはこれらのイベントを中継する仕組みも開発しています.現在のところ,WebWorkersによるworkerとの通信と,Webブラウザ同士の通信が実現されています.つまり,チャット(ピクトチャット含む)やカードゲーム,動画像の同期などに利用することが可能です.

実際のプログラミングで使用するメソッドはたったの2つで,onとemitです.onはキーワードとコールバック関数を定義するメソッドで,emitはキーワードと(必要があれば)パラメータを送信するメソッドです.例えば上の図の状況を定義する場合には以下のような記述となります. たったこれだけの記述でobj_a,obj_b,gui間のイベント処理が実現します.

次に,Webサーバを中継点として,Webブラウザ同士で上記のイベントをやり取りする場合のプログラミングについて説明します.キーワードは「broadcast」です.イベントキーワードに「broadcast」が入っていた場合,Webサーバを通じて同時に接続しているWebブラウザ上のオブジェクトに通知されます.実際には以下のようになります. ボタンが押された際の送信キーワードに「broadcast」を加えるだけで,Webブラウザ同士の通信を実現できます.この場合,接続しているどのWebブラウザ上でも良いのでボタンをクリックすると,各Webブラウザ上の該当する処理が実行されます.言い忘れましたが,キーワードは「|(パイプ記号)」で繋げることで,いくつでも指定できます.

Nylonはhttps://github.com/sudahiroshi/Nylon2で公開中です.
今後,何回かに分けてNylonについて説明していきます. このエントリーをはてなブックマークに追加

2011年8月27日土曜日

JavaScriptとC#の連携方法(2)

ずっと前にJavaScriptとC#の連携について投稿しました.まずはDOM要素にアクセスするところだけ投稿して,その後C#からJavaScriptの関数を呼んだり,その逆を投稿しようとして後回しにしたまま忘れていました.と言うことで,C#からJavaScriptの関数を呼ぶ方法および,JavaScriptからC#の関数を呼ぶ方法について説明します.
今回は「Microsoft Visual Web Developer 2010 Express」(以下VWD)を使用して,C#を使ってSilverlight3アプリケーションを作成しました.HTMLファイルはVWDによって自動生成されたものに若干手を入れています.

また,ものすごく単純化して,以下の2つの機能を持つ一つのアプリケーションを作成します.Silverlight→JavaScriptの例として,Silverlightで一つのTextBoxと一つのButtonを設置し,Buttonが押されたらJavaScriptにTextBoxの内容を受け渡して,JavaScriptでAlertを使って受け取った内容を表示します.次にJavaScript→Silverlightの例として,HTMLで一つのTextと一つのButtonを設置して,Buttonが押されたらSilverlightにTextの内容を受け渡して,SilverlightのTextBoxに受け取った内容を表示します.

C#からJavaScriptの関数を呼ぶ方法

まず,呼び出される関数(JavaScript)を生成します.VWDが自動生成したMHTMLファイルは,"<プロジェクト名>TestPage.html"という名前で保存されています.その中の(今回は)21行目から56行目にJavaScriptの記述があるので,そこに以下の内容を追加します.見れば分かると思いますが,messageを受け取って,その内容をalertとして表示するだけです.
注意事項として,"<プロジェクト名>TestPage.html"は,コンパイルの度に標準状態に戻されます.悲しい思いをしないよう,バックアップを作成しながら作業してください.


次に,上記alertData関数を呼び出すC#のプログラムを記述します.VWDでは当たり前ですが,C#のプログラムは,TextBoxやButtonを配置した後,そのButtonをダブルクリックすれば,面倒な関数定義などは自動でやってくれます.念のため断っておくと,MainPage.xaml.csというファイルを編集します.
プログラムでは,button1が押された場合に,textBox1の内容をalertDataに送るという処理を記述します.実際の呼び出しはInvokeメソッドで行います.第一引き数に呼び出したい関数名を文字列で与え,第二引き数にオブジェクト型の配列として,実際にalertDataに与えたい引き数を列挙します.


この例では使用しませんが,例えばalertDataが三つの文字列を受け取るのであれば,次のように記述します.

System.Windows.Browser.HtmlPage.Window.Invoke( "alertData", new Object[] { "mouse", "cow", "tiger" } );


JavaScriptからC#の関数を呼ぶ方法

C#→JavaScriptは簡単でしたが,JavaScript→C#はちょっとやっかいです.順に説明するので,焦らずにいきましょう.先ほどと同じように,まずは呼び出される関数から記述します.記述するファイルは先程と同じくMainPage.xaml.csです.


一目瞭然ですが,messageを受け取って,textBox1に代入しています.ScripttableMember()は,外部からアクセスできるメソッドであることを示します.次に,外部からプログラム内部にアクセスできるように設定するため,App.xaml.csに変更を加えます.具体的には,27行から始まるApplication_Startup関数に追加します.以下にApplication_Startup関数を全て掲載しますが,実際には4行目を追加することになります.


次に,HTMLに入力欄とボタンを設置し,さらにSilverlightオブジェクトにIDを付加してJavaScriptからアクセスできるようにします.1行目から4行目を追加し,7行目に「id="slobj"」を挿入してください.1〜4行目では,入力欄とボタンを設置しています.ボタンがクリックされたらsendSL関数(後述)を呼び出します.記述するファイルは"<プロジェクト名>TestPage.html"です.繰り返しますが,"<プロジェクト名>TestPage.html"はコンパイルの度に標準状態に戻されます.


最後に,"<プロジェクト名>TestPage.html"にsendSL関数を記述します.これは,前述したalertData関数に続けて記述してください.

見ての通り,HTMLのIDからSilverlightオブジェクトを取得(3行目)して,呼び出したい関数を記述(4行目)するだけです.4行目のMainPageは,App.xaml.csのApplication_Startup関数に記述した文字列なので,対応さえしっかりしていれば変更可能です.
このエントリーをはてなブックマークに追加

2011年4月8日金曜日

OS Xでpowを使ってみる

今回も、MeSHから離れた話題です。

powとは何か?

平たく言うと、Mac OS X上で動作する、Rackサーバです。Rackとは何かと言うと、ruby言語を利用して作成したアプリケーションとWebサーバとのインタフェース統一するためのライブラリです。SinatraもRailsも、Rackを介して動作するようになっています。powは、Rackの仕組みに沿って開発されたプログラムを、お手軽に試す際に有効です。

例えば、Webアプリケーションを試しに作ってみようとして、ホワーンとアイディアが浮かんでいる段階を想像してください。Railsなら、とりあえずプロジェクトを作成して、DBの構造を決めて、scaffoldして・・・mongrelなどを動かして、Webブラウザから確認するという流れになります。Sinatraだと、DBにテーブルを作って、app.rbを作って、mongrelなどを動かして、Webブラウザから確認するという流れになります。もう少し開発が進むと、Passengerなどを使ってApacheと連携するフェーズに進みます。このとき、動作ディレクトリを設定ファイルに登録するのが面倒になります。小規模なプロジェクトだと、ディレクトリまるごとコピーして新旧の動作を比較したいとか、別ディレクトリのプロジェクトと同時進行するなどの場合、いちいち設定ファイルを書き換えるのが嫌になります。このようなときに、Webアプリケーションを簡単に公開するための仕組みがpowです。

powの設定

powはpow.cxで公開されています。最初、ダウンロードのリンクが見つからなくて右往左往したのは秘密です。powのインストールは、以下のコマンドを実行するだけです。
$ curl get.pow.cx | sh
これだけで、様々な設定が行われ、ホームディレクトリに「.pow」というディレクトリが作られます。次に、RailsやSinatraなどで作成したRackアプリケーションのディレクトリのシンボリックリンクを作成します。例えば「/Users/admin/sinatra/test」というディレクトリであれば、
$ cd ~/.pow
$ ln -s /Users/admin/sinatra/test
と入力してください。これで~/.pow/testが作成されます。以上で設定は終了です。後は、Webブラウザを起動して、「http://<作成したシンボリック名>.dev/」にアクセスすればアプリケーションを利用できます。

実際に試してみる

それでは実際にサンプルプログラムを用いて説明していきます。事前に用意するものは、SinatraとRackです。いずれもgemコマンドでインストールできます。
$ gem install rack
$ gem install sinatra
次に、Sinatraを使った簡単なサンプル「app.rb」と、そのプログラムをRackから呼び出すための設定ファイル「config.ru」を作ります。


いずれも、「/Users/admin/sinatra/test」ディレクトリに作成してください。

後は、Webブラウザから「http://test.dev/」にアクセスすると、ブラウザ上に「Hello, world」の文字が表示されると思います。

app.rbを書き換えた場合は、powの再起動が必要となります。「/Users/admin/sinatra/test」直下に「tmp」ディレクトリを作成し、
$ touch tmp/restart.txt
を実行してください。powは、tmp/restart.txtのタイムスタンプを見て、自身を再起動するかどうか決定します。

うーん、シンプル。Mac OS Xを使っていて、RailsやSinatraを使っている人はpowも使ってみてください。数は少ないですが、日本語の記事も出てきています。
Node.js+CoffeeScriptで書かれた「Pow」がカッコ良すぎる件 | Rails Hub情報局
powを使ってdevelopment環境で複数のrailsアプリを同時に動かす | YomuKaku Memo このエントリーをはてなブックマークに追加

2011年2月28日月曜日

RubyとOLEでPowerPointを遠隔操作してみる

MeSHの枠組みを拡張する?

MeSHは、これまでWebブラウザ上で様々なものを動作・同期させることを念頭に置いてきました。しかし、「様々な」という概念を拡張していくと、ネイティブアプリケーションまで辿り着きます。せっかくプラットフォームに依存しないよう開発してきたのですが、「できない理由を説明するより、できることを証明してから悩もう」の精神に則り、ネイティブアプリケーションを操作してみたいと思います。今回は技術検証なので、Windows上にWeb簡易サーバを構築し、ネイティブアプリケーションを制御してみます。

RubyとOLE

OLEはObject Linking and Embeddingの略で、簡単に言うとWindowsアプリの連携を図るための根幹です。対応したプログラムであれば、プログラムを制御したり、プログラム中のイベントに応じて自作プログラム中のメソッドを実行することができます。このような便利な機能を使わない手はありません。早速プログラムを制御してみましょう。

普通は、Microsoft関連の便利な機能を使うためにはVisualStudioなどを使うことになるのですが、RubyにはWIN32OLEというありがたいクラスが作られています。通常、WIN32OLEの説明にはWordやExcelが用いられるのですが、実はPowerPointと連携するとプレゼンが便利になります。と言う訳で、RubyからPowerPointを制御しようというのが本日の記事になります。

基本的な制御

WIN32OLEが何であるかはRubyist Magazineの該当記事を読んでください。ここでは、あくまでPowerPointの制御のみ(簡単に)解説します。いや、深いところを訪ねられても解説できないというのが本音です。

事前準備として、Windowsを使っていて、PowerPointを持っていて、Rubyをインストールしていることが必要となります。それでは早速PowerPointで何かファイルを開いてみて下さい。次にirbを起動して以下の内容を打ち込んでみて下さい。

この3行を入力すると、PowerPointがプレゼンテーションモードになると思います。2つ以上のファイルを開いている場合には、どちらのファイルが対象となるか私には分かりませんので、1つだけ使用して下さい。

2行目は、OLEの仕組みを利用して、PowerPointとやり取りするための書き方です。3行目は、メソッドがチェーンしていますが、順番に「アクティブなプレゼン」の「スライドショー」を「実行」して「その状態」を得る。という(様な)意味です。細かく言うと間違っているかも知れませんので、鵜呑みにしないようお気を付けください。

それでは、ここで得られたオブジェクトviewを利用してPowerPointを制御してみます。制御のためのメソッドの中でも代表的なものを掲載します。上のプログラムの続きと思っておいてください。それぞれ、意味はコメントに書いておきます。


具体的にPowerPointを制御する

ここまで分かれば、後は適当なポート番号でHTTPを想定して待ち受けて、「次へ」や「前へ」のボタンを作成して、ボタンが押されたらview.Nextやview.Previousを実行してあげれば、Webブラウザから制御できます。つまり、iPhoneなどからプレゼンテーションの制御を行なうことが可能となります。

と言うことで作成したのが次のソースです。1つのファイルの中にRubyスクリプト、HTMLファイル、JavaScript、CSSが入っているので見づらいと思いますが、このファイルだけコピーすれば使えるという気楽さを念頭に置いているのでご容赦ください。(無駄に)AJAXを使っているので、ページ遷移などは発生しません。

前準備:
・以下のソースを保存する。
・WindowsのIPアドレスを調べておく

使い方:
1.PowerPointでプレゼンしたいファイルを開く。
2.rubyで以下のソースを実行する。
3.WindowsのWebブラウザ(動作検証はChromeで行ないました)からhttp://localhost:8080/に接続する。
4.ボタンをクリックして動作させる。
5.うまくいったらiPhoneなど、別ホストからも試してみる。

注意事項:
・セキュリティソフトの動作状況によっては、iPhoneなどから接続できない場合があります。その場合は一時的にセキュリティソフトをオフにしてお試しください。
・ユーザインタフェースは手抜きです。簡単なHTMLとCSSなので、気になった方は書き直してください。
・JavaScriptも冗長です。ご容赦ください。
・ctrl+CでRubyスクリプトが停止しない場合があります。対処法としてctrl+Cを3回ほど連打して、ブラウザ側でリロードなどをすると停止します。対処法をご存じの方、ご連絡いただければ幸いです。

将来的な拡張:
・現在のページ番号と全ページ数が手元に表示されるといいな
・ついでにストップウォッチ機能も欲しいな(スタート・ストップは手動で良いかな?)
・ページ番号をメニューから選択して飛ぶ機能も欲しいかも?
・現在表示しているページや次ページの内容が手元で確認できるといいかも

検証に使用したソフトウェアとバージョン:
・Microsoft Windows Vista ServicePack2 (Windows 6.0.6002)
・Microsoft Office PowerPoint 2007(12.0.6535.5002) SP2
・ruby 1.8.7 (2009-06-12 patchlevel 174) [i386-mswin32]
・Google Chrome 9.0.597.98
・iPhone 3GS (iOS4.2.1)

このソフトについて

ライセンス:GPLv3
免責事項:無保証です。このソフトを使用することによって生じた損害に対して、作者は一切の責任を負いません。

このエントリーをはてなブックマークに追加

2011年2月12日土曜日

Mac OS XのApache設定

MacBook Air

ちょっと前になりますが、MacBook Air 11'モデルを入手しました。System7以来、久しぶりにMacに回帰しました。CPUなどのスペックには特筆すべきことはない、いや、むしろ今のご時世では貧弱と言わざるをえないのですが、予想外にキビキビ動作します。特にスリープへの移行と復帰は感動ものです。しかも、OS XはBSD UNIXの血を受け継いでいるので、Macは立派なUNIXマシンです。これまでWindows環境上でプログラミングしようとして、数々の苦労をしてきた経験からすると、様々な言語や環境がプリインストールされ、まともに動作することだけで嬉しくなってしまいました。(私とWindowsの相性がわるいことは否定しません。Apacheの設定がうまくいかないとか、Rubyでソケットを使うとうまくいかないとか、CGIの設定がうまくいかないとか、MySQLの設定がうまくいかないとか、昨日まできちんと動いていたシステムが上手く動かなくなったとか、環境設定ファイルがどこにあるのか分からないとか・・・。結局、Windows上で足掻くよりも、仮想計算機環境でDebianを動かす方が楽です。)

細かいところでは、controlキーが正規の位置(Aの左)に配置されているのも好印象です。

まずはApacheの設定

OS Xでは、RubyもApacheもMySQLもPythonもVIMもプリインストールされています。ターミナルを開けば、基本的なUNIXコマンドは使用できます。うーん、幸せ。あ、別にUNIXコマンドが好きなわけじゃなくて、設定を変更したら素直に反映される環境が好きなだけです。

と言うことで、まずはApacheの設定を変更してみます。前提条件として、ユーザ名はadminと仮定して話を進めます。この場合、ホームディレクトリは/Users/adminに、Webサイトのホームディレクトリは/Users/admin/Sitesになります。

準備編

まずは、Webサーバの起動です。標準状態では起動されません。
システム環境設定 ー 共有 ー Web共有にチェックをつけて「入」にしてください。
Webブラウザから
http://localhost/~admin/
にアクセスすると、エラーが出ずに「あなたのWebサイト。」というタイトルのページが見られることを確認しましょう。もしWebサーバが起動していなければエラーとなります。

気が向いたら、適当なHTMLファイルを作ってWebブラウザで確認してみましょう。ファイルを置くフォルダは前節で説明しています。

CGIスクリプト編

CGIスクリプトは、管理者しか設置できないようにする場合と、ユーザが自由に拡張できる場合のどちらでも設定できます。とりあえずお手軽に試せるように、ホームディレクトリ内に置いたファイルを実行できるようにします。
(1)cgi-binディレクトリを作る
mkdir /Users/admin/Sites/cgi-bin

(2)Webサーバ(Apache2)の設定ファイルを書き換える
主な設定は/etc/apache2/httpd.confに書いてあるので編集する。このとき、一般ユーザの権限では書き込みできないので
cd /etc/apache2
sudo vi httpd.conf
という風にsudoを付けてから書き換える。
#AddHandler cgi-script .cgi
という行があるので、行頭の「#」を取ってこの設定を有効化する私の環境では、396行目でした。


(3)adminユーザのWeb設定を変更する
OS Xでは、ユーザごとのWeb設定ファイルが存在するので変更しましょう。
設定ファイルは/etc/apache2/usersに全ユーザ分が入っています。今回はadminと言う名のユーザなので該当ファイルは
/etc/apache2/users/admin.conf
です。またしても一般ユーザでは書き込めないのでsudoを付けて編集しましょう。
cd /etc/apache2/users
sudo vi admin.conf
元々のファイルには、下記の内容(全6行)が書いてあります。

それを、以下の内容に変更してください。具体的には7行目以降を追加します。Optionsの行は、Apacheのドキュメントを参照して欲しいが、簡単に言うと「CGIの実行を許可」し、「ファイルの一覧表示を拒否」し、「言語の自動判別機能を不使用」としています。


(4)Webサーバの再起動
設定を変えたらWebサーバの再起動をしましょう。コマンドラインから再起動する方法が分からなかったので、システム環境設定 ー 共有 ー Web共有のチェックを一度外し、一呼吸おいてから再度チェックを付けることで再起動できます。

(5)CGIファイルを作る
CGIなので言語は何でも良いが、せっかく標準でインストールされているのでRubyを例に取ります。
cd /Users/admin/Sites/cgi-bin
vi test.cgi
と入力して、test.cgiを作ってみましょう。サンプルを以下に示します。

たった3行のプログラムです。試しにターミナルから実行してみましょう。viを終了したら、ruby test.cgiと入力すると、画面にcontent-type…以下略と表示されるはずです。もし表示されない場合はプログラムがきちんと入力されていないので確認して下さい。次に、このプログラムに実行属性をつけます。説明は省略しますが、ファイル作成直後のパーミッションは644なので、自分は読み書きが可能、他の人は読むだけです。これでは実行できないので、755の状態にします。
chmod 755 test.cgi
これでコマンドラインから直接実行できるはずです。試しに
./test.cgi
と入力してみると、確かに実行できます。

ここまで終わったら、次はWebブラウザから見てみましょう。
http://localhost/~admin/cgi-bin/test.cgi
にアクセスして、画面にOKと表示されれば(文字通り)OKです。

続く・・・のか? このエントリーをはてなブックマークに追加