Null.ly

1 note &

Perfume Hackathon の思い出

だいぶ前のことになりますが、 弊社で Perfume Hackathon を主催したりしてました。雨の中足元の悪い中お越しいただいた皆様には感謝です。初めてのイベント主催で慣れないところもありましたが、参加者のみなさんのお力添えで何とかやり遂げることが出来ました。

自作の紹介

手前味噌になりますが、自分は Three.js の DOMRenderer という DOM 要素を 3D のオブジェクトとして扱えるレンダラを使った作品を制作しました。DOMRenderer はメジャーではないせいか、参考資料がなくて大変でした。

大部分のコードを mohayonao さんの実装を参考にさせて頂きました。感謝!

参加者の作品紹介

制作内容に特に制限を設けなかったこともあって、バラエティあふれる内容となりました。

at_akada さん

BVH のモーションデータを元に新しい BVH を生成する作品です。動きがものすごいです。Python で製作されました。

shikaimonjo さん

サウンドと同期してブロックの大小が変化する作品です。Twitter のつぶやきに応じて色が変化するギミックも。Processing で製作されました。

nnkgw さん

Windows/Mac 両対応のミニマムかつ移植性の高い作品です。OpenGL と C++ で製作されました。

hitsujiwool さん

JavaScript 向けの BVH パーサを作成されました。非常にクリーンなインタフェースです。

雑感

  • 参加して下さった方それぞれの成果が形になってよかった
  • 募集をかけた後に日程を変更してしまい参加できない人が出てしまった
    • 申し訳ないことをしてしまった…
  • 会場の場所をもう少しわかりやすく出来ると良かった

1 note &

東京 Node 学園 5 時限目の思い出

だいぶ前のことになりますが、 東京 Node 学園に参加してました。個人的なことになりますが、初めて LT なんぞをさせて頂きました。

イベント全体のレポートが Nifty さんのブログに上がっています。

イベント通してどれも素晴らしい内容だったのですがJxck さんの Meteor の発表が特に興味深い内容でした。当時はリリース間もない中だったと思うのですが、ハイペースなキャッチアップとリサーチは見習っていきたいと思いました。

発表のネタ

openFrameworks + ofxFaceTracker で顔の特徴点を取り出してさくらの VPS に予め設置しておいた Node のサーバに飛ばして、会場内の PC に WebSocket (Socket.IO) で配信する、というちょっと変わり種っぽい発表をしました。

当日は、サーバのキャパシティを超えるアクセスがありビジー状態になったりして、大成功とは言えなかったのですが、ビジュアル的に見栄えのするデモにはなったと思うので良かったかなと思います。

動画

発表資料

ソースコード

1 note &

ofxWorkshop の思い出

だいぶ前のことになりますが、 ofxWorkshop に参加してました。10 人ほどの集まりで、濃厚な二日間でした。

やったこと

  • シンプルなパーティクルエンジンの制作
  • 既存ライブラリのアドオン化 (libnoise)
  • アドオンの制作・またはアドオンを使った openFramework アプリケーションの制作

覚えたこと

  • アドオンを探すには ofxAddons というサイトがおすすめ
  • アドオンも setup(), update(), draw() のモデルで作ったほうが扱いやすい
  • openFrameworks は C++ なので世の中にある C++ 向けのライブラリを使うことが出来る
  • アドオンの形にして openFrameworks から扱いやすい形に出来ると生産性向上
  • openSourceVFX.org に C++ で作られたライブラリがまとめられている
  • クラス変数の初期化は代入よりコンストラクト初期化のほうが高速
  • ライブラリ内のデータを ofVec, ofPoint など、openFramework が提供するクラスに変換出来るとアプリケーションから使いやすくすることが出来る

雑感

  • 3D の知識必須!
    • 最初の一歩がパーティクルエンジンだったので 3D プログラミングの経験は必須と感じた
  • C++ 難しい
  • バイナリアンすごい
    • ライブラリの組み込みの ARGB のビットマップデータを RGBA な unsigned char* に変換したりとか
  • やっぱり Kinect 大人気
    • 制作に Kinect を用いている人が 3, 4 名ほどいらっしゃいました
  • 普段 Web やってる人は結構多い
  • 久しぶりの openFrameworks だったので感を取り戻すまでが大変だった

作ったもの

ワークショップの二日目はほぼハッカソンで黙々と制作するという感じになりました。僕は Node と ofxFaceTracker を組み合わせたデモを作りました。次の週に東京 Node 学園の LT が控えていたため、発表用の制作も兼ねたりしちゃいました。

2 notes &

Socket.IO を詠む会の思い出 Part 1

弊社で実施した Socket.IO を詠む会 第一回目のおさらいをまとめ。ぶっきらぼうに書いているのであまり参考にならないかも……。

今回は listen() して標準出力に socket.io started と出力されるまでのまとめ。


ファイルツリー

lib/
├── logger.js
├── manager.js
├── namespace.js
├── parser.js
├── socket.io.js
├── socket.js
├── static.js
├── store.js
├── stores
│   ├── memory.js
│   └── redis.js
├── transport.js
├── transports
│   ├── flashsocket.js
│   ├── htmlfile.js
│   ├── http-polling.js
│   ├── http.js
│   ├── index.js
│   ├── jsonp-polling.js
│   ├── websocket
│   │   ├── default.js
│   │   ├── hybi-07-12.js
│   │   ├── hybi-16.js
│   │   └── index.js
│   ├── websocket.js
│   └── xhr-polling.js
└── util.js

ライブラリの本体は lib/ ディレクトリ内に格納されている。


エントリポイントを知る

ライブラリのエントリポイントは package.jsonmain プロパティに書かれている。

Socket.IO の場合は ./index.js がスクリプトの開始位置。


index.js

./lib/socket.iorequire して module.exports に代入しているだけ。


./lib/socket.io.js

var socket = require('socket.io');

上のコードの socket のプロパティは lib/socket.io.js で exports されたものになる。

var socket = require('socket.io')
  , io = socket.listen(80);

listen() メソッドで Socket.IO が立ち上がる。


./lib/socket.io.js の listen() メソッド

色々と分岐が挟まるが、最終的には Manager オブジェクト (./lib/manager.js に定義) のファクトリメソッドとなっている。途中、分岐しているのは可変長引数を受け付けるため。

例としてはこんな感じ。

var io = socket.listen();

引数なし。

var io = socket.listen(80);

ポート番号を指定

var httpServer = require('http').createServer();
var io = socket.listen(httpServer);

HTTPServer のインスタンスを指定

var io = socket.listen(function() {
  console.log('Socket.IO is listening.');
});

コールバック関数を指定

var httpServer = require('http').createServer();
var io = socket.listen(httpServer, function() {
  console.log('Socket.IO is listening.');
});

HTTPServer のインスタンスとコールバック関数を指定

var httpServer = require('http').createServer();
var io = socket.listen(httpServer, { log: false }, function() {
  console.log('Socket.IO is listening.');
});

HTTPServer のインスタンスとオプション (後述) とコールバック関数を指定

さまざまな呼び出しをならしてから new Manager() で Manager の生成を行なっている。つまるところ listen() メソッドの戻り値 ioManager クラスのインスタンスとなる。

HTTPServer のインスタンスを引数に渡さなかった場合は listen() メソッド無いで HTTPServer を生成する。


Manager (./lib/manager.js) コンストラクタ

引数に取るのは、HTTPServer のインスタンスとオプションのハッシュ。コンストラクタで行われる処理はこんな感じ。

  • HTTPServer のインスタンスを Manager.server にセット
  • ネームスペースを初期化
  • デフォルトのネームスペースを Manager.sockets にセット
  • 引数にとったオプションを デフォルト値上書き

  • HTTPServer にイベントハンドラを設定

    • error イベント → エラーをログに出力
    • request イベント → Manager.handleRequest() に処理を委譲
    • upgrade イベント → Manager.handleUpgrade() に処理を委譲
    • close イベント → Manager.garbageCollection() のタイマをリセット (clearInterval)
    • listening イベント → Manager.garbageCollection() のタイマを設定 (setInterval)
  • 1.0 の前方互換向けの処理? 詳細不明…

  • 標準出力に socket.io started と出力。

Manager クラスは EventEmitter を継承している。

1 note &

Connect/Express で HTTPS 接続を強制する

Connect/Express と everyauth を組み合わせて別のサービスのログインを実装しようとした際に、OAuth 2.0 の HTTPS 強制に引っかかったりしたので、HTTP でアクセスしてきたユーザを HTTPS にリダイレクトするようなミドルウェアを作った。Rails でいうところの config.force_ssl = true みたいなやつ。

重要なのが 21-27 行目。これで非 SSL 通信でアクセスしてきたユーザを SSL 通信にリダイレクトすることが出来る。

1 note &

Heroku で omniauth のコールバックで “Request-URI Too Large”

Heroku で運用している社内システムを Google Apps と連携させるために omniauth を使って認証するようにしたら、認証から帰ってくるコールバック時にこんなエラー出力された。

Request-URI Too Large
WEBrick::HTTPStatus::RequestURITooLarge

どうやら Webrick の制限で 1024 文字以上の URL は受け付けないみたい。(引っかかった URL は 1251 文字もあった。)

Thin や Mongrel を使うか、Webrick の本体のコードを修正することで制限を緩和できるが、今回は相手が Heroku のため、Thin に切り替えることで対応した。

Gemfile に以下の行を追加。

gem 'thin', :group => [:production]

以下のコマンドで Gemfile.lock を更新してから Heroku に push する。

$ bundle install --no-deployment
$ git commit -a -m 'use thin web server on production environment'
$ git push heroku master

これで Request-URI Too Large を回避することができた。やったね。

1 note &

gem コマンドで “no such file to load — zlib”

さくらの VPS (CentOS 6.2) で rbenv + ruby-build で Ruby をセットアップした後、gem コマンドを実行したらこんなエラーが出てきた。

$ gem install bundler
ERROR:  Loading command: install (LoadError)
    no such file to load -- zlib
ERROR:  While executing gem ... (NameError)
    uninitialized constant Gem::Commands::InstallCommand

zlib が無いってさ。おそらく Ruby のビルド時に zlib がリンクできなかったんだな。

$ sudo yum install zlib-devel
$ rm -fr .rbenv/versions/1.9.2-p290
$ rbenv install 1.9.2-p290

ビルドが終わったら…

$ rbenv rehash
$ gem install bundle
Fetching: bundler-1.1.3.gem (100%)
Fetching: bundle-0.0.1.gem (100%)
Successfully installed bundler-1.1.3
Successfully installed bundle-0.0.1
2 gems installed
Installing ri documentation for bundler-1.1.3...
Installing ri documentation for bundle-0.0.1...
Installing RDoc documentation for bundler-1.1.3...
Installing RDoc documentation for bundle-0.0.1...

やったー。完。


追記 (2012/04/23 16:12)

今度は監視ツールの god をインストールして実行しようとしたところでエラー。


$ god
/home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': no such file to load -- openssl (LoadError)
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/net/https.rb:92:in `'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god/conditions/http_response_code.rb:2:in `'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god.rb:46:in `'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god/cli/run.rb:89:in `block in run_daemonized'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god/cli/run.rb:87:in `fork'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god/cli/run.rb:87:in `run_daemonized'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god/cli/run.rb:21:in `dispatch'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/lib/god/cli/run.rb:8:in `initialize'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/bin/god:122:in `new'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/gems/god-0.12.1/bin/god:122:in `'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/bin/god:23:in `load'
    from /home/user/.rbenv/versions/1.9.2-p290/gemsets/user/bin/god:23:in `
'

さっきと同じように openssl-devel を入れてから Ruby をコンパイルし直す。

$ sudo yum install openssl-devel
$ rm ~/.rbenv/versions/1.9.2-p290
$ rbenv install 1.9.2-p290
...
$ gem install god
$ rbenv rehash

これで god コマンドでエラーしなくなった。ぐったり。

1 note &

Titanium Mobile で XML-RPC するためのモジュール作った

どういうわけかこのご時世に Titanium Mobile にて XML-RPC で通信しなければいけないという事態になってしまったので、ライブラリを書いてみた。既存のものはレスポンスのパーザーがなかったりいまいち使いにくかったので superagent 風に使えるようにしてみたよ。


使い方


var xmlrpc = require('./lib/xmlrpc');

var client = xmlrpc.createClient({
  url: 'https://api.example.com/XML-RPC'
, username: 'xxxx'
, password: 'xxxx'
});

client
  .call('foo.methodName')
  .param(10)  // int
  .param(10.1)  // double
  .param(null)  // nil
  .param(undefined)  // nil
  .param(true)  // boolean
  .param(false)  // boolean
  .param([1, 2, 3])  // array
  .param([1, 2, [3, 4]])  // nested array
  .param({ hello: 'world' })  // struct
  .param([1, 2, { hello: 'world' }]) // nested array and struct
  .param(new Date())  // dateTime.iso8601
  .param('hello')  // string
  .param(function() {})  // ignored!
  .end(function(res) {
    if (!res.ok) {
      return Ti.API.warn('error!');
    }
    Ti.API.info(res.body.params);
  });

call() でメソッド名を指定して、param() をチェインしてパラメータを追加していく。終わったら end() でリクエストを実行。

コールバックメソッドの res.body.params にレスポンスがオブジェクトで格納される。res.ok を見てエラーハンドリングする感じ。

2 notes &

CSS セレクタのシングルコロンとダブルコロンの違い

ここ経由。気になったので調べてみた。結論先に書いちゃう。

シングルコロン

  • 擬似クラスに使われる。
  • 元となる要素の一部や状態をあらわすときに使われる。
  • a:link とか。

ダブルコロン

  • 擬似要素に使われる。
  • 元となる要素を基準に、別の要素を指し示すときに使われる。
  • .clearfix::before とか。

と、ここまでは仕様上のお話。Internet Explorer が関わってくるとそうは問屋は卸さない。

Internet Explorer 特有の動作

  1. IE6/7/8 は擬似要素と擬似クラスの記法を区別せず、すべてシングルコロンで記述する。
  2. IE6 に限って擬似要素・擬似クラスのコロンは何個書いても解釈される。 (.clearfix:::before と書いても OK)
  3. IE7 以降はコロンの数を厳密に解釈する。
  4. IE7/8 はダブルコロンの記法に対応していない。擬似要素でもシングルコロンで記述しなければならない。
  5. IE9 以降は仕様に準拠する。(ただし後方互換のため擬似要素をシングルコロンで書いても解釈される。)

上記を踏まえて .clearfix::before がそれぞれどのように解釈されるかというと…

  • IE6: .clearfix の後に続く要素が選択される。 (.clearfix::before.clearfix:before と解釈される。)
  • IE7: ::before 擬似セレクタに対応していないため無視される。
  • IE8: IE7 と同様無視される。
  • IE9: ::before 擬似セレクタに対応。.clearfix に後に続く要素が選択される。

珍しく、レガシー IE の中で IE6 だけが (表面上) 標準に準拠した動作をするケースとなる。

関連かも