Subscribed unsubscribe Subscribe Subscribe

枕を欹てて聴く

香炉峰の雪は簾を撥げて看る

NPAPI拡張 iTunes Daemon

f:id:Constellation:20100311060719p:image
iTunesで今なっている曲の情報を取得するAPIを提供するGoogle Chrome拡張, iTunes Daemonを書きました. Windowsでしか動きません. COMを使っているからです...
Constellation/iTunesDaemon · GitHub

まだまだ実験段階ですが, installしたい方はこちらのlinkから拡張をdownloadしてください.
Extension

APIについて

外部APIしか提供しません.
また, 拡張機能のID/itunes_daemon.jsを用意しているので,

function itunes_daemon(){
  console.log('iTunes Daemonがinstallされているよ!!');
}
var script = document.createElement('script');
script.type = "text/javascript";
script.src  = 'chrome-extension://hdippioaffhbpbooejnmbikgiojfobhg/itunes_daemon.js';
document.head.appendChild(script);

iTunes Daemonの存在確認ができ, また

var ITUNESDAEMON = 'hdippioaffhbpbooejnmbikgiojfobhg';
chrome.extension.sendRequest(ITUNESDAEMON, {
    action: 'currentTrack',
  }, function(res){
    if(res.success){
      console.log(res.content);
    } else {
      // currentTrackがない
      console.log(res.content);// => undefined
    }
});

で, 画像にあるように情報を取得できます. capsuleいいですね, PLAYERのなかではStay with Youが一番はまりました.
Taberarelooと連携させたら, Now listeningとかTwitterにPostしたりできそうです.
以下はNPAPIについてです. 破滅の技術, NPAPIに興味のない方はここまでで.

NPAPI

で, 滅びの技術NPAPIなわけです. なんにしても情報が少なかった...

Chromium

この街のすべてを敵に回しても, 止めるわけにはいかないんだ!! *1

木山春生

みたいなことがあるならNPAPI触るといいと思います. Chromium拡張機能としてNPAPIをinstallし, その拡張のページ(background_page)だけで機能させるpublic:falseの機能があるので, security的にもそんなに気にしなくてすみそうです.

いちおう動くpluginとしてこれがあるので, これのソースコード見てみたり(かなり汚い...), wrapper libraryであるnixysaソースコードを読んだりすると動作がつかみやすいです. ただし現在, nixysaで作ってもChromeでは動かないので注意.
あと, Memory management in NPAPI | ColonelPanicのメモリマネジメントはぜひ. NPAPIのメモリがどうなっているのか, JSにでたObjectはいかにしてGarbage Collectされるのかがよくわかります.
そして同じところのBuilding a firefox plugin – part one | ColonelPanicからのシリーズも非常に参考になります.

などなど, ためになる情報は他にあるので, 概要だけ.

概観

NPAPIは基本的にC用APIなので, 関数pointerの入ったstructを扱いながらごにょごにょするC + objectiveってもの感じのものです. まあC++でやらかすので, きれいにclassにwrapする必要があります.
GitHubにあげたソースコードに, JSのObjectをC++でうまくwrapする例として, Track classが作ってあるので, 一回見ていただけると「へーなるほど」ってなるかもしれません.
また, C++ std::stringをJS Stringに変換するStringToNPVariantなどを見るとある程度どういう風な形をしているかつかめると思います.

structに関数pointerをつめて, それをclassとします. memoryはNPNetscapeFuncsのinstanceからcreateobjectを使ってメモリ確保+class適用を行います. これによって出来上がったNPObjectはリファレンスカウントを持っており, これがJS Contextに出たときにGCの走る基準になります.
また, このobjectを型情報(String/Int/Double/Object/BoolなどJS内部側の)とともにwrapしたものがNPVariantであり, これがJSのvalueに当たります. これは自分で作るのではなく, NPAPIのマクロを使って作りましょう.

あと, 注意事項として, WebKitのEnumerationのNPAPIはbugってるとか何とからしいです...
そしてはまりやすいところとして, NPAPIのvalueは基本的に呼び出し側が破棄の責任を持ちます. C言語APIですから...
NPAPIの関数を使って得た値はNPNetscapeFuncsのinstanceからmemfreeを使って開放するようにしてください. これは, utf8fromidentifierとかでもです. これをはじめ忘れてて, すごい勢いでメモリが...

また, JS Contextに出た値については, JSのほうで勝手にGC走らせてくれます. 適切なDeallocation関数のPointerをclassとして設定していればですが.

iTunes

Appleさん提供のiTunes for Windows COM SDKを使いました.
わかったことは, BSTRは超使いにくいってことです.

補足

JS楽しい. IE6も滅んだので(名目上), これで人に気兼ねなくJSをお勧めすることができますね. C++大好きな友人に今度, NPAPI使えばC++書けるよって言ってうまく釣り上げて, JSに引き込もうと画策しています.
今回実はVisual Studio一回も立ち上げてません. mozilla-centralのpluginのsample codeからVCのgenerateする部分もらってきたり, Vimで書いて, Rakefileでcompileしてやってました. これはひどい.
困ったことがあって, Chromium, 拡張をreloadできるのはいいんですが, DLLをopenしたままなんですね. Windowsはopenしてるファイルを削除するLinuxみたいなことができないので, Chromium再起動させないとrecompileできないという...

*1:超電磁砲が終わるまでに一度はネタにしたかった