メモ

調べたり思いついたりしたことをメモします

Open Web Board の BLE

11/15に大阪でハッカソンがあり、Open Web Board というものをもらってきました。

f:id:uenoshin:20141206002353j:plain

右上の小さいUSBが給電用で、左のHDMIでモニタに接続して画面出力できるようになっています。 メモリ1G、ストレージ8G、Bluetooth4.0対応、WiFi802.11b/g/n対応、など盛りだくさんです。Androidスティック並みの小さいサイズなのにがんばってますね。発熱するらしいので専用ケース付きでした。 OSは FirefoxOS v1.4 だそうで、ちょっとだけ古いです。最新に入れ替えてみたくてうずうずします。

HDMIで画面につながるのですがタッチパネルでないのでマウス必須です。写真右下のUSBのクチはマウス専用になりそうですがBluetoothマウスを使ってもいいかもしれません。 RaspberryPi や Flame とは何が違うだろうかという点が気になりますが、やはりこのボードはBLEがポイントになるように思ったのでBLEをどう実装しているのかちょっとだけ調べてみました。

BLEデモというアプリが予め入っているので adb pull でこれを吸い出して中身を展開します。 bleclient.gaiamobile.org という名前で入っていました。 デモという名前だけあってかなり軽量でシンプルなアプリでした。

使っている主なオブジェクトは3つあります。

  1. navigator.mozBluetooth

  2. navigator.mozSettings

  3. navigator.mozBle

1,2は普通に既存実装されている BluetoothManager と SettingManager です。 3つめの mozBle だけは mozilla-central や mozilla-aurora にも見当たりませんので、おそらく独自拡張かと思えます。 この mozBle にどんな機能があるか気になるところですが Gecko 側の webidl や C++ソースもありませんし、当然MDNにも乗っていないので現状はこのデモアプリのJavaScriptソースから読み解くしかなさそうです。

ble_demo.js上で使われているメソッドは次の通りでした。

registerClient()
unRegisterClient()
connectBle()
disconnectBle()
searchService()
getIncludeService()
readRemoteRssi()
executeWrite()
scanLEDevice()
registerForNotification()
getCharacteristic()
readCharacteristic()
writeCharacteristic()
getDescriptor()
readDescriptor()
writeDescriptor()

メソッドの名前からおおよそ推測するしかありませんが、Gattプロファイルに準じたR/Wができるようです。

Bluetooth GATT | Specifications | Bluetooth Development Portal

また、この mozBle はなぜかイベントハンドラを持ってないようです。 代わりに BluetoothAdapter に対してMDNに記載のないハンドラを登録している処理があったので、BluetoothAdapter に対しても拡張が加えられているのかもしれません。 BluetoothAdapter - Web API Interfaces | MDN

今日現在ではAPIが公開されていない(少なくとも私は発見できていない・・)ようなので実際にBLEを使った作品を作ってみるにはデモアプリを解析しながらやるしかないようです。といっても割と分かりやすいデモアプリだと思いますのでそれほどハードルは高くないでしょうけど。 年末年始の休みにはなにか作ってみたいのでそれまでに公開があることを期待したいと思います。

FirefoxOSビルド環境用の Dockerfile

ubuntu上のFirefoxOSビルド環境を作って壊してを繰り返すことが多くなってきたのでコンテナ型仮想環境に手を出しました。

dockerいいですね、docker。気に入りました。

Vagrant+VirtualBoxでは重くて使えなかったのですが、dockerならほとんどストレスなく使えます。

1. dockerのインストール

導入の仕方は公式に丁寧に書いてありますのでリンクだけ貼ります。

Ubuntu - Docker Documentation

企業の中の人など、プロキシ越しでないと外へアクセスできない事があります。そんなときは /etc/default/docker に

export http_proxy="http://*******"

こんな感じに環境変数を設定すれば docker pull ができるようになります。

2. イメージの作成

ubuntuに幾つかのパッケージを足したイメージを作成します。

Dockerfile のサンプルは下の方に貼っています。コピペしてubuntu上のどこかに置いてください。置いた場所を仮に /path/to/Dockerfile だとして下記のようにすればイメージが出来上がります。

$ sudo docker build -t my_img /path/to/

my_img の部分は任意の名前です。それなりに時間はかかりますがこれで my_img という名前のイメージが作られます。 Dockerfileの中身は下のほうで紹介します。

3. コンテナの作成

できたイメージを元にコンテナを作り、シェルを実行します。

$ sudo docker run -it --name my_cont my_img /bin/bash

my_contの部分は任意の名前です。ほぼ一瞬でコンテナが作られ、シェルが起動します。これで仮想環境上でのシェルが扱えます。

4. FirefoxOSのビルド

デスクトップクライアント版で試しました。ここで紹介する Dockerfile では develop というユーザを登録しているので、developで作業します。ここからは仮想環境内で作業します。

$ su develop
$ cd /home/develop/
$ git clone https://github.com/mozilla/gecko-dev

Building the B2G desktop client - Mozilla | MDN

MDNを参照しながら mozconfig を作り、

$ ./mach build

でビルドが通る状態となります。

5. Dockerfile

超簡単ですがこれで動きました。下記の内容を Dockerfile というファイル名で保存します。

FROM ubuntu:12.04

RUN useradd -d /home/develop -m -s /bin/bash develop
RUN echo develop:develop | chpasswd
RUN echo 'develop ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
RUN apt-get update

RUN apt-get -y install autoconf2.13
RUN apt-get -y install bison
RUN apt-get -y install bzip2
RUN apt-get -y install ccache
RUN apt-get -y install curl
RUN apt-get -y install flex
RUN apt-get -y install gawk
RUN apt-get -y install gcc
RUN apt-get -y install g++
RUN apt-get -y install g++-multilib
RUN apt-get -y install git
RUN apt-get -y install ia32-libs
RUN apt-get -y install lib32ncurses5-dev
RUN apt-get -y install lib32z1-dev
RUN apt-get -y install libgl1-mesa-dev
RUN apt-get -y install libx11-dev
RUN apt-get -y install make
RUN apt-get -y install vim
RUN apt-get -y install unzip
RUN apt-get -y install zip
RUN apt-get -y install libgtk2.0-dev
RUN apt-get -y install libdbus-glib-1-dev
RUN apt-get -y install yasm
RUN apt-get -y install libasound2-dev
RUN apt-get -y install libgstreamer0.10-dev
RUN apt-get -y install libgstreamer-plugins-base0.10-dev
RUN apt-get -y install libxt-dev

プロキシ環境の場合は、Dockerfileの先頭あたり(apt-getよりも前の行)に環境変数の設定を入れれば良いです。

ENV http_proxy "http://*******"
ENV https_proxy "https://*******"

FirefoxOS開発用端末Flameの日本語ビルド

FirefoxOSの開発用端末Flameが2014.07に日本で発売されました。

出荷時はFirefoxOSのv1.3が入っていて、しかも非日本語版なので多くの人は自分なりの環境をビルドして焼くことでしょう。というかそういう使い方をするためのモノだと思います。

日本語ロケールを有効にした最新版ビルドの作り方はあちこちのサイトで紹介されつつありますが、やってみて失敗することも多いです。私はちょっとだけハマりました。

そこで私なりに作り方を整理しておこうと思います。

B2Gのビルド

最初にやることは、ごく標準的なB2Gのビルド環境の構築です。ざっと説明しますが分からなくなったらMDNを参考に勉強しましょう。

Firefox OS - Mozilla | MDN

事前準備として、MDN に書いてある通りビルドに必要な各種パッケージをインストールします。私はubuntu12.04を使っているので下記のようにしました。MDNには各環境別に必要なパッケージのインストール例が説明されているので自分の環境に合わせてセットアップしてください。

$ sudo apt-get install autoconf2.13 bison bzip2 ccache curl flex gawk gcc g++ g++-multilib git ia32-libs lib32ncurses5-dev lib32z1-dev libgl1-mesa-dev libx11-dev make libxml2-utils

あと、adb・fastboot が必要です。AndroidSDKを引っ張ってくるなどしてadbとfastbootを入手し、パスを通しておきましょう。

次にB2Gリポジトリを clone してきます。ここでは作業ディレクトリパスを /path/to/ と書いていますが環境に合わせて読み替えてください。

$ cd /path/to/
$ git clone git://github.com/mozilla-b2g/B2G.git

そのディレクトリへ移って config.sh を実行します。

$ cd B2G
$ ./config.sh flame

gaia や gecko など各種ソースがダウンロードされますので結構な時間が掛かります。気長に待ちましょう。 config.sh が終わったらビルドが出来る状態になっています。

エミュレータと違って実機をビルドするときは、ビルドの最初のフェーズで実機内に入っているファイルを adb pull で抜き出してくるようです。そのため Flame を USB でつないで adb が使える状態であることを確認しておきましょう。

$ adb devices
List of devices attached
f03641d1        device

adb devices でデバイスがアタッチされていることが見えればOKだと思います。ダメだった場合udevの設定をしましょう。FlameをUSBでつないだ状態で lsusb を使えば下のような出力が見えると思います。

$ lsusb
Bus 003 Device 003: ID 05c6:9025 Qualcomm, Inc.

ベンダIDが「05c6」ということなので、udev のルールに加えれば良いです。

$ sudo vi /etc/udev/rules.d/52-firefoxos.rules

下記の1行を書く

SUBSYSTEM=="usb", ATTR{idVendor}=="05c6", MODE="0666", GROUP="plugdev"

これでudevサービスを再起動するなり、マシンを再起動するなりすれば adb で Flameにアクセスできるようになります。

ちなみに上記のudevの設定は 52-firefoxos.rules なんてファイルを勝手に作りましたが、多くの人はすでに 51-android.rules みたいなファイルがあるでしょうので、その中に行追加するだけでもOKです。

この状態でビルドできるようになったはずです。B2Gを clone したパス上で build.sh を動かします。

$ cd /path/to/B2G
$ ./build.sh

ビルドに失敗したらMDNを見ながら環境を見直ししてください。

無事にビルドが出来たら Flame に焼きます。

$ ./flash.sh

これで最新版の FirefoxOS が焼けたことになります。

日本語版のビルド

さて標準的なビルドが出来たら、今度は日本語版にチャレンジします。 下記に書く事はMDNの Building multilocale の部分とほとんど同じで日本語向けにしただけです。

gaia

/gaia/locales/ の直下には日本語用のディレクトリがありません。別途ダウンロードします。

$ cd /path/to/B2G/gaia/locales/
$ hg clone http://hg.mozilla.org/gaia-l10n/ja

こうすれば ja というディレクトリが出来上がります。

次に取ってきた ja ディレクトリを読み込むように設定します。languages_dev.json をコピって、新しいファイルを作り、それを編集することにします。

$ cd /path/to/B2G/gaia/locales/
$ cp languages_dev.json languages_ja.json
$ vi languages_ja.json

中身は英語と日本語以外をざっくり削除する程度です。下のようにします。

{
  "en-US"     : "English (US)",
  "ja"        : "日本語"
}

これで gaia で日本語を有効にするセットが出来ました。これらのセットをビルドに組み込むため、B2G直下に .userconfig を書きます。

$ cd /path/to/B2G
$ vi .userconfig

中身は下のようにします。

export LOCALE_BASEDIR=$PWD/gaia/locales
export LOCALES_FILE=$PWD/gaia/locales/languages_ja.json
export GAIA_DEFAULT_LOCALE=ja

gecko

B2G直下に移動して gecko 用のファイルを取ってきます。

$ cd /path/to/B2G
$ hg clone http://hg.mozilla.org/l10n-central/ja gecko-l10n/ja
$ hg clone http://hg.mozilla.org/build/compare-locales

設定のため再び .userconfig を編集します。今度は下の行を追加します。

export L10NBASEDIR=$PWD/gecko-l10n
export MOZ_CHROME_MULTILOCALE="ja"
export PATH="$PATH:$PWD/compare-locales/scripts"
export PYTHONPATH="$PWD/compare-locales/lib"

ここまでで日本語化ビルド用の設定は完成です。

日本語キーボード

表示が出来ても入力が出来なければいまいちなので日本語入力ができるようにします。

追記:ツリーの中に日本語辞書が取り込まれたようで、下記の打ち消し線部分は対応不要になりました。

まず作業ディレクトリに ipadic というディレクトリを作ります。

$ cd /path/to/B2G/gaia/apps/keyboard/js/imes/jskanji/dict
$ mkdir ipadic

この ipadic ディレクトリは時々名前が変わるみたいです。しばらく前は src という名前だった気がしますが今は ipadic のようです。 jskanjiの直下にあるREADMEを読みましょう。

次に任意のディレクトリに ipadic-2.7.0.tar.gz を展開します。 ipadic-2.7.0.tar.gzはここから取ってきます。

/24435/ipadic-2.7.0.tar.gzをダウンロード - IPAdic legacy - SourceForge.JP

取ってきた tar.gz を展開して中に入っている *.dic を全部、先ほど作ったディレクトリの中へコピーします。

$ tar xvzf ipadic-2.7.0.tar.gz
$ cd ipadic-2.7.0
$ cp *.dic /path/to/B2G/gaia/apps/keyboard/js/imes/jskanji/dict/ipadic/

この状態で dict ディレクトリ上にて make します。 しばらく掛かりますが dict、dict.utf8 というファイルが同フォルダ上に出来上がるはずです。

$ cd /path/to/B2G/gaia/apps/keyboard/js/imes/jskanji/dict
$ make

最後にこの日本語辞書を使うためのキーボード設定です。 再び.userconfig に設定を書きます。

export GAIA_KEYBOARD_LAYOUTS=en,jp-kanji

ビルド

いちど objdir-gecko、out を消してから再ビルドします。そうしないと L10NBASEDIR が設定されてないとのエラーになりました。

$ cd /path/to/B2G
$ rm -rf objdir-gecko
$ rm -rf out
$ ./build.sh

これで再ビルドが終わったら Flame に焼いて完了です。

$ ./flash.sh

日本語キーボードを有効にするには設定アプリからキーボードを選択してください。 あんまり優秀なキーボードではありません。。 Google日本語入力とか使いたい・・。

Firefox for Android をビルドする手順

FirefoxブラウザのAndroid版ビルド手順を書いておきます。

詳細は Mobile/Fennec/Android - MozillaWiki を参照ください。若干古いようなので試しに最新版でやってみました。

ubuntu12.04(64bit) で実行しています。ここでは /opt/workspace というワークディレクトリ上で作業するものとします。

ビルド環境の準備

環境の準備はMDNを見てください。

$ mkdir /opt/workspace
$ cd /opt/workspace
$ hg clone https://hg.mozilla.org/mozilla-central/

Android開発環境の準備

AndroidSDKとNDKが必要になります。 最新を落としてきて展開します。今日(2014.07.18)の最新は下記の通りのバージョンでした。

$ mkdir /opt/workspace/android/
$ cd /opt/workspace/android/

$ wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2
$ wget http://dl.google.com/android/adt/adt-bundle-linux-x86_64-20140702.zip
$ tar xfj android-ndk-r9d-linux-x86_64.tar.bz2
$ unzip adt-bundle-linux-x86_64-20140702.zip
$ ./adt-bundle-linux-x86_64-20140702/sdk/tools/android update sdk -u
$ ./adt-bundle-linux-x86_64-20140702/sdk/tools/android update adb

sdkのアップデートに時間がかかるのでGUIで特定のバージョンだけを選んでもいいでしょう。

普段 Android の開発をやっている人は既に入っているかもしれませんが ant が必要です。

$ sudo apt-get install ant

同じくJDKがいります。以前のAndroidは sun-java6 が必要だったのですが現在はopenjdk7でもOKです。ちなみに試してみたところ openjdk6 でも通りました。インストールしたら update-alternatives で切り替えます。

$ sudo apt-get install openjdk-7-jdk
$ sudo update-alternatives --config java

mozconfig の設定

mozconfig ファイルを Android 用に作成します。

$ vi /opt/workspace/mozilla-central/mozconfig

---------mozconfigの中身---------
ac_add_options --with-android-ndk="/opt/workspace/android/android-ndk-r9d"
ac_add_options --with-android-sdk="/opt/workspace/android/adt-bundle-linux-x86_64-20140702/sdk/platforms/android-20"
ac_add_options --enable-application=mobile/android
ac_add_options --target=arm-linux-androideabi
ac_add_options --with-ccache
mk_add_options MOZ_OBJDIR=./mybulid-android
---------mozconfigの中身---------

sun-java6 を使っている人は android-20 の部分を android-18 に変えてください。

mozilla-central をビルド

つくった mozconfig を使ってビルドします。

$ cd /opt/workspace/mozilla-central
$ ./mach build

無事にビルドが終わったら apk ファイルを作ります。

$ ./mach package

ファイルは /opt/workspace/mozilla-central/mybulid-android/dist/gecko.apk に出来上がります。

すでにAndroid端末がUSBで繋がっていてadbが通る状況になっているならインストールもできます。

$ ./mach install

これでAndroid端末へインストールされます。もちろん普通に adb install でもいいですが。

端末上では "Fennec $USER" のような表示名でアイコンが出来ていると思います。ここの名前は /opt/workspace/mozilla-central/mobile/android/branding/unofficial/configure.sh の中身をあらかじめ編集しておくことで変更できるようです。

さて、、できあがった Firefox for Android英語版です。

日本語で使いたい場合は Multilocale 版をビルドしなければなりません。

多言語版のビルド

Multilocale 版をビルドするには mozharness を使います。

まずワークディレクトリ上で mozharness を取得し、その中に入っている standalone_mozilla-central.py をコピーして編集します。

$ mkdir /opt/workspace/multilocale
$ cd /opt/workspace/multilocale
$ hg clone http://hg.mozilla.org/build/mozharness
$ cp mozharness/configs/multi_locale/standalone_mozilla-central.py myconfig.py

myconfig.py の BUILD_DIR を編集します。すでに mozilla-central でビルドできる環境を持っているので、そこへのパスを書きます。

$ vi myconfig.py

---------myconfig.pyの中身(部分抜粋)---------
BUILD_DIR = "/opt/workspace/mozilla-central"
---------myconfig.pyの中身(部分抜粋)---------

そして mozconfig を作成します。先ほど作ったものを使い回せば楽なのでコピーしてきました。

$ cp /opt/workspace/mozilla-central/mozconfig .

mozconfig 内の MOZ_OBJDIR と myconfig.py 内の OBJDIR を合わせておく必要があるようです。 myconfig.py 内のデフォルトは "objdir-droid" だったのでそれを mozconfig 側にも設定しました。(どちらにあわせても良いと思いますが)

$ vi mozconfig

---------mozconfigの中身(部分抜粋)---------
mk_add_options MOZ_OBJDIR=./objdir-droid
---------mozconfigの中身(部分抜粋)---------

これでビルド可能です。

$ mozharness/scripts/multil10n.py --cfg myconfig.py

/opt/workspace/mozilla-central/objdir-droid/dist/gecko.apk へ apk ファイルまで一気に作成されます。

Android端末にインストールするとその端末の言語設定に応じた言語で起動できると思います。

Firefox OS に独自のWebAPI(DeviceAPI)を追加する方法

Geckoには予め多くのWebAPIが実装されていますが、独自のAPIを追加したいと思ったら改造するしかありません。 改造は案外簡単にできるようになっていますので HelloWorld を出力するサンプルを作ってみました。

Firefox OS と書きましたが普通のFirefoxブラウザでもまったく同様です。

事前準備

mozilla-central から hg pull 等して環境一式を持ってきてビルドできる状態にします。

※ここでは2014.06.21のナイトリーを使っており、Geckoは33.0a1です。

WebIDLの作成と登録

ここから本題です。

webidl

WebIDLはインタフェース定義です。JavaScriptから呼ぶインタフェースを定義する記述言語で、W3C等で規定されるWebAPIはこの書式が使われます。

WebIDLを入れる場所は mozilla-central/dom/webidl/ です。 この場所に HelloWorld.webidl というファイルを新規作成します。 中身は簡単な例としてこんな内容にします。ここではPrintメソッドを呼んだら文字列を返すインタフェースにしています。

[Constructor]
interface HelloWorld
{
    [Throws]
    DOMString Print();
};

moz.build

次に同じディレクトリ上にある moz.build 内の WEBIDL_FILES にファイル名を追加します。追加する場所はアルファベット順にソートして入れる必要がありますので場所に気をつけましょう。 これを書いておかないと先ほどのwebidlファイルがビルドに含まれてくれません。

'GetUserMediaRequest.webidl',
'HelloWorld.webidl',           ←※コレを追加
'History.webidl',

バインディングの設定

Bindings.conf

webidlと、ネイティブ層実装をつなぐためのバインディングを設定します。 ファイルは mozilla-central/dom/bindings/Bindings.conf です。 ファイル内のDOMInterfacesにHelloWolrdのバインディングを追加しましょう。

'HelloWorld': {
    'nativeType': 'mozilla::dom::HelloWorld',
}

本体の実装

バインディングから実際に呼び出されるネイティブコードを作成します。 専用のディレクトリを用意してその中に実装を置くようにすると置き場所がすっきりして気持ちいいです。 ここでは mozilla-central/dom/mywebapi を掘ってその中に作ることにします。

$ cd mozilla-central/dom
$ mkdir mywebapi

mywebapi というディレクトリを掘ったら mozilla-central/dom/moz.build を編集します。 PARALLEL_DIRS に mywebapi を追加してやればディレクトリを認識してくれてビルドが通るようになります。

'xbl',
'xslt',
'mywebapi',         ←※コレを追加
]

mywebapiに移動して HelloWorld.h、HelloWorld.cpp、moz.build の3ファイルを作ります。中身はこれです。

HelloWorld.h の中身

#include "mozilla/ErrorResult.h"
#include "nsWrapperCache.h"
#include "jsapi.h"
#include "nsIDocument.h"
#include "mozilla/dom/TypedArray.h"
#include "nsString.h"

namespace mozilla {
namespace dom {

class HelloWorld  : public nsISupports,
                    public nsWrapperCache
{
public:
    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(HelloWorld)

    HelloWorld( nsPIDOMWindow* aWindow);
    ~HelloWorld();

    nsIDOMWindow* GetParentObject() const
    {
        return mWindow;
    }

    virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;

    static already_AddRefed<HelloWorld>
    Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);

    void Print(nsString& ret,ErrorResult& aRv)
    {
        nsString* tmp = new nsString((nsString::char_type*)L"Hello World!",24);
        ret = *tmp;
    }

private:
    nsRefPtr<nsPIDOMWindow> mWindow;

};

} // namespace dom
} // namespace mozilla

HelloWorld.cpp の中身

#include "HelloWorld.h"
#include "mozilla/dom/HelloWorldBinding.h"
#include "mozilla/HoldDropJSObjects.h"
#include "nsContentUtils.h"

namespace mozilla {
namespace dom {

NS_IMPL_CYCLE_COLLECTION_CLASS(HelloWorld)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HelloWorld)
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(HelloWorld)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END

NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(HelloWorld)
  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END

NS_IMPL_CYCLE_COLLECTING_ADDREF(HelloWorld)
NS_IMPL_CYCLE_COLLECTING_RELEASE(HelloWorld)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(HelloWorld)
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END

already_AddRefed<HelloWorld>
HelloWorld::Constructor(const GlobalObject& aGlobal,
                        ErrorResult& aRv)
{
    nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aGlobal.GetAsSupports());
    if (!win) {
        aRv.Throw(NS_ERROR_FAILURE);
        return nullptr;
    }

    nsRefPtr<HelloWorld> hello = new HelloWorld(win);
    if (!hello) {
        aRv.Throw(NS_ERROR_FAILURE);
        return nullptr;
    }
    return hello.forget();
}

HelloWorld::HelloWorld( nsPIDOMWindow* aWindow)
{
    mWindow = aWindow; // For GetParentObject()
    SetIsDOMBinding();
}

HelloWorld::~HelloWorld()
{
}

JSObject*
HelloWorld::WrapObject(JSContext* aCx)
{
    return HelloWorldBinding::Wrap(aCx, this);
}


} // namespace dom
} // namespace mozilla

moz.build の中身

EXPORTS.mozilla.dom += [
    'HelloWorld.h',
]
SOURCES += [
    'HelloWorld.cpp',
]

FAIL_ON_WARNINGS = True

FINAL_LIBRARY = 'gklayout'

ビルド

あとは普通にビルドすれば出来上がります。

$ cd mozilla-central
$ make -f client.mk

テストコード

HelloWorldの Print(); を呼び出すサンプルコンテンツです。出来上がったb2gやfirefoxでこのコンテンツを表示させてみれば先ほど作成した Print() が文字列を返してくれることを確認できます。

<!DOCUTYPE html>
<html>
<head>
    <meta charset=UTF-8>
    <script>
        function Hello() {
            var helloWorld = new HelloWorld(window);
            var moji = helloWorld.Print();
            document.getElementById("str").textContent=moji;
        };

    </script>
</head>
<body onload="Hello()">
    <p id="str">
    </p>
</body>
</html>

コンピュータ名の付け方に規則性を持たせてみる

今週のお題「名前をつける」

新しくPCをセットアップするとき、コンピュータ名を設定しなくてはなりません。 WindowsLinux・・のように複数台のPCが家や会社にある場合、それぞれにどんな名前を付けるか、よく悩むポイントです。

自分の中では規則性を意識することに決めていました。 といっても単にシリーズ物で統一するだけです。エンジニアの日常にあまり接点のないジャンルから選ぶと気分が変わっていいですよ。

以前に使ったことがあるいくつかの例を書き記しておきます。

1. 音楽系

chopin, mozart, bach, elgar, vivaldi のような音楽家シリーズです。 文化的になった気がします。

2. 芸術系

gogh, picasso, monet, davinci のような画家シリーズもいいですね。

3. 童話系

andersen, carroll, grimm 文学の中でも童話ものです。

4. ネタ系

monju, fugen, tsuruga, mihama 原発シリーズです。熱いハイスペックマシンに付けるといいかもしれません。

タブレットが帰港するメインマシンの事を「母艦」と呼ぶことが多いですし、最近なら艦船の名前シリーズで付けるのもいいかもしれませんね。

Doxygenで綺麗な日本語の納品用PDFを出力する方法

後々ドキュメントを自動生成する目的で、C,C++等でコーディングするときはDoxygenJavaDoc用のコメントを記載することが多いです。

Doxygenは普通に使うとデフォルトではHTMLを出力してくれます。普段はそれでいいのですが、1ファイルでポンと渡せる方が便利な場合がありますよね。

DoxygenのHTML出力は大量のファイル群で出力されちゃうのですが、たまにそれだと困る事があるのです。たとえば

  • 客先へ納品するとき
  • 社外とか、チーム外の誰か他の人に渡す時
  • 印刷したいとき

のような場合です。PDFで出力できれば便利なのに、と思うのが人情です。

もちろんDoxygenはPDF出力ができますのでそこは問題ありません。 問題は日本語フォントが美しくなかったり、しおりが文字化けしたり、ハイパーリンクがうまく動作しなかったり、というトラブルが多くてなんだかもやもやしてしまう点にあります。

いくつか手段を模索した結果、たどりついたのは思いがけず簡単で安易な方法でした。

いったんRTFで書き出す

これです。Doxygen用の設定ファイルに、下記のような変更を加えればよいでしょう。

GENERATE_RTF           = YES
RTF_HYPERLINKS         = YES

これでRTFファイルが生成されてくれます。デフォルトでは refman.rtf というファイルが出来上がりました。

PDFに変換する

Microsoft WORD2010 を使いました。生成されたRTFをWORDで開き、Ctrl+Aで全選択してメイリオあたりへフォント変更。 その後、「名前を付けて保存」→「PDF形式」で保存できます。

PDF形式を選んだ時点で「オプション」ボタンが出てきますのでそこで「しおり」の出力設定なんかが可能です。

この方法で作成したPDFなら日本語環境でもかなり綺麗に表示できますので、納品用とかの用途で使用できるのではないでしょうか。