2013年7月12日金曜日

Android 4.xにしたらonPreviewFrameが呼ばれなくなったので対策した

画像認識やAR用途などでカメラからの映像をキャプチャしたい場合、onPreviewFrameで行うことがあると思う。
しかしAndroid 2.x (Gingerbread)では呼ばれていたonPreviewFrameが、Android 4.x (Ice Cream Sandwich)で動かしたら呼ばれなくなっていた。 その対策方法を見つけたのでメモしておく。

問題の起こるコード
class CameraPreviewSurface implements SurfaceHolder.Callback, Camera.PreviewCallback {

    // 中略
    
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        if (mCamera != null) {
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.setPreviewCallback(this);
            } catch (IOException e) {
                if(camera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mCamera.stopPreview();

        // 中略

        mCamera.setParameters(params);
        mCamera.startPreview();

    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {

        // 中略

    }
}

そして、以下が対策済みのコード
class CameraPreviewSurface implements SurfaceHolder.Callback, Camera.PreviewCallback {

    // 中略
    
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        if (mCamera != null) {
            try {
                mCamera.setPreviewDisplay(holder);
                // 不要 mCamera.setPreviewCallback(this);
            } catch (IOException e) {
                if(camera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mCamera.stopPreview();

        // 中略

        mCamera.setParameters(params);
        mCamera.setPreviewCallback(this); // stopPreviewを呼んだら、startPreviewを呼ぶ前にsetPreviewCallback
        mCamera.startPreview();

    }

   @Override
   public void onPreviewFrame(byte[] data, Camera camera) {

        // 中略

     }
}

stopPreviewを呼ぶとそれ以前のsetPreviewCallbackは無効になるらしい。

参考にしたページ
Android Camera - A Problem I Spent Almost Twenty Hours On
Thanks!

2013年3月30日土曜日

NATIVE INSTRUMENTS KOMPLETE AUDIO 6 を Linux から使う

Linuxでマルチチャンネル録音がしたくなりUSBオーディオインターフェースをいくつか検討した結果、ついに手頃な物を見つけた。

それがこのNATIVE INSTRUMENTS KOMPLETE AUDIO 6だ。

実際Ubuntu 12.04のデスクトップPCと、Raspbian “wheezy”のRaspberry Pi、それぞれに接続してみたらあっさりと認識された。

入力をWAVファイルに録音するには、arecordを使って以下のようにすれば良い。
arecord -c 6 -f S32_LE -r 48000 output.wav
オプションに'-c 6'とある通り6 ch同時録音している。
1〜6 chを自由に指定できると良いのだが、未だ成功していない。

2013年3月29日金曜日

CentOS 6.4 に GitLab 5.0.0 をインストールしてはまったこと

インストールは基本的にはGitLabのドキュメントの通り進めれば良いGitLabのinstallation.mdだけではだめで、gitlab-recipesのドキュメントも参考にしながら進めていく。
とはいえ見落としなどいくつかの躓きがあったのでメモ。

躓きポイント1
CentOSのadduserはuseraddのエイリアスである。よってDebian系のadduserとは使えるオプションが違う。
useraddでgitという名前のユーザーを追加する場合は次の通り。
useradd -c "GitLab" git


躓きポイント2
nginx用の設定ファイルはgitlab-recipesのこれを/etc/nginx/conf.d/gitlab.confとして書き込む。
さらに、/etc/nginx/conf.d/default.confと、/etc/nginx/conf.d/gitlab.confが重複するので、/etc/nginx/conf.d/default.confの中身を全てコメントアウトする。

躓きポイント3
そのままではnginxが/home/git以下にアクセス出来ないので、次のようにしてnginxをgitグループに加えることでアクセス権を与えるようにする。
usermod -G git nginx
ちなみに、アクセス出来ない時のエラーは以下のようにして確認できる。
tail -f /var/log/nginx/gitlab_error.log

躓きポイント4
アクセス権を適切に設定する。
chmod 710 /home/git
chmod 700 /home/git/.ssh
chmod 600 /home/git/.ssh/authorized_keys
git cloneやgit pushはssh経由で行われるが、関連するファイルやディレクトリのアクセス権を適切に設定しておかないとクライアントからのアクセス時にパスワード無しの鍵を登録しているにも関わらずパスワードの入力を求められ先に進めなくなる。
自分が犯した失敗は/home/gitのアクセス権が710以外になっていたのと、/home/git/.ssh/authorized_keysのモードが600以外になっていたことである。
特に/home/gitのグループアクセス権に実行権限のみを付けておくことは重要だ。この実行権限がないとwebからもgitからもアクセス出来なくなる。
設定を間違えたときのエラーの詳細はサーバー側で
tail -f /var/log/secure
としてログを眺めつつ、クライアントから
git clone git@servername:myrepo.git
などとすることで確認できる。


躓きポイント5 (2013.4.4追記)
インストール後にGitLabサーバーのFQDNを変えた場合への対応方法。
1. gitlab/config/gitlab.ymlの設定
gitlab:
    host: 新しいFQDN

2. Emails have incorrect URL in link to project の問題で配信されるメール中のリンクが変わらないので、gitlab/config/environments/production.rbに次の一文を追記。
config.action_mailer.default_url_options = { host: '新しいFQDN', port: 80 }

3. gitlab-shell/config.ymlのgitlab_urlの値の設定
gitlab_url: "http://新しいFQDN/"

4. 1〜3の対応をした上で、gitユーザーになってGitLabを再インストール
bundle install --deployment --without development test postgres
必須ではないかもしれないが、これを実行しないとgitlabサービスをリスタートした直後に配信されるメール中のURLが最初は新しく設定したURLになるものの、すぐに元に戻ってしまっていた。 想像だが非同期のタスクが動き出すとDB内の古い値でgitlabのスクリプト内の変数を書き換えてしまうのではないだろうか。

参考資料
gitlabhq / doc / install / installation.md
gitlab-recipes
GitLab 5.0 を CentOS 6.4 にインストールした

2013年2月2日土曜日

MacでGIMP 2.8.xの動作が重い時の対処方法

2.8からMacにネイティブ対応したGIMPだが、キーボードを押したときに固まる現象が起きており使い物にならなかった。
しかしついに対処方法が分かったのでメモしておく。

この問題を解決するにあたり様々な言語環境でGIMPの挙動を調べた。
その結果、Google日本語入力が入っていると固まることが判明した。

しかし、Google日本語入力は普段使いで恩恵を受けているので消したくない。
そこで編み出したのが以下の手順である。

1. 以下の図ように言語とテキスト(私の場合は英語にしているのでLanguage & Text)の環境設定から、ローマ字入力にはことえりを使うようにする。
2. 次に、同じ画面のリストをスクロールして、ひらがなのみGoogle日本語入力を使うようにする。
3. そしてGIMPを使うときはことえりのローマ字入力モードにしたままにしておく。

以上の手順で、GIMP は固まること無く動作させることが出来た。

検証環境
Mac OS X 10.8.2
GIMP 2.8.3
Google日本語入力 1.0.556.1

2012年12月31日月曜日

openFrameworksのMacアプリにアイコンを設定する

openFrameworks(この記事の執筆時点では0073)のprojectGeneratorで作成したプロジェクトからビルドしたMac OS Xアプリにはアイコンを設定するには、Xcode 4上の意外な部分の変更が必要だったのでメモしておく。

1. まず通常の手順(参考)でアイコンを追加した。しかしこれだけだと.appにはアイコンは設定されない。

2. この時足りないのは以下の画像のように、Copy Bundle Resourcesでアイコンファイルをコピーするように設定されていなかった。
Xcode 4のBuild Phases画面
このCopy Bundle Resourcesの項目は、通常の手順でCocoa Applicationを作成した場合は最初から存在するので意識することはないのだが、projectGeneratorで作成したプロジェクトにはなかった。
Info.plistやicnsの設定ばかり疑ってしまったが、意外な落とし穴だった。

2012年11月13日火曜日

Mac OS Xの普段使いで爆速で計算する方法

Macを使っているときに簡単な計算をしたいだけなら、計算機アプリを起動する必要はないことを知ったのでメモ。

やり方は、
Command+Space でSpotlightを開いて計算したい式を入れるだけ。
入力する式の例. 1+2

定数eやpi、さらに括弧も使える。例. (1+2)/3
三角関数も使える。例. sin(pi/4)
べき乗は^。例. 5^2
log()は常用対数だ。例. log(10)

およそ2秒で計算完了。

※ GCDやOpenCL等の記事を期待していらした方、ご期待に添えずすみません。

2012年10月5日金曜日

node.js + express + socket.io 仕様変更対応

expressとsocket.ioのAPI仕様が変わったらしく、適当にアップデートしたら動かなくなってしまった。
対処方法は下記の通り。

サーバー側
var express = require('express')
  , app = express();
  , io = require('socket.io').listen(app.listen(3000));

app.configure(function(){
 app.use(express.static(__dirname + '/public'));
});

クライアント側 HTML
<script src="/socket.io/socket.io.js"></script>

参考にしたページ
「Cannot GET /socket.io/socket.io.js」の解決法 (Node.js v0.8.0/express v3.0.0/socket.io v0.9.6)

2012年10月3日水曜日

vimで一括処理

文字コードや改行コードを一括で変換したい時や特定の文字列を置換したい時に、nkfがなくても、sedを知らなくても、vimさえあればなんとかなります。

1. Vimを起動する

2. カレントディレクトリを置換対象のファイルがあるディレクトリに移動する
:cd foo

3. 引数リストにファイルを追加する
例. カレントディレクトリ以下の拡張子がcのファイル。
:args  **/*.c

4. 確認する
:args

5. 置換する
例. エンコーディングをutf-8、改行コードをLF、タブをスペースにする。
:argdo fenc=utf8 ff=unix et | update

余談
argdoの他にbufdo、tabdo、windoもある。
argsの他に個別に追加削除するためのargaddやargdeleteもある。

2012年5月14日月曜日

UnityとKinectとOpenNIを組み合わせる

UnityとOpenNIとKinectかXtion Proを使って、Unity内のオブジェクト操作する環境を構築する方法についてまとめておこうと思う。

前提条件: OpenNI一式とUnityが動作していること。
検証した環境: Mac OSX Lion、Unity 3.5、Xtion ProまたはKinect


  1. OpenNIのダウンロードページから"PrimeSene Unity Wrapper Unstable Build v0.9.7.4"(2012.5.14時点の最新)をダウンロードする
  2. ダウンロードしたopenni_unity_toolkit-0.9.7.4.zipを展開するとOpenNI_Unity_Toolkit-0.9.7.4.unitypackageが出来る。
  3. UnityのProjectにOpenNI_Unity_Toolkit-0.9.7.4.unitypackageをインポートする。方法はメニューから"Assets"->"Import Package"->"Custom Package ..."でOpenNI_Unity_Toolkit-0.9.7.4.unitypackageを選択。
  4. Unity 3.5を使っている場合、3でインポートしたパッケージ内のNIInput.csにエラーが起こるのでここを参考に次の通り修正する。295行目の"return Input.GetRotation(deviceID);"を"return Quaternion.Euler(Vector3.zero);"。306行目の"return Input.GetPosition(deviceID);"を"return Vector3.zero;"にそれぞれ書き換える。
  5. "OpenNI"->"Prefabs"->"Sample Prefabs" "OpenNI"->"Sample Scenes"にある各種サンプルをHierarchyに追加して動かしてみる。
以上だが、Cheetah3Dで自作したキャラクターにリグを組んでインポートしたら、回転と前後左右が逆になった。右手系と左手系の変換が上手くいっていないようで、久しぶりにBlenderを使おうかと。

参考
[Unity][Blender] BlenderからUnityへキャラクターをインポートする

2012.5.14 手順の5番目の記述が間違えていたので修正


2012年2月29日水曜日

GitoliteをMac OS X Lion Serverにインストールする

クライアントからgitolite-adminがclone出来ずに非常に悩んだのだが、最終的には次のサイトを見て分かった。
gitolite で Git リポジトリへの SSH アクセスを制御する
Gitolite git clone error

ポイント
  1. ssh-keygenで生成するファイルは、普段利用しているid_rsa.pubでは無く、別のものにする。
  2. Appleの提供するGitを使うならサーバーにXcodeをインストールする。
  3. 2でインストールされたGitを使うなら、サーバーのgitユーザーのホームフォルダにある.gitolite.rcに下記の一行を追加する。
  4. $ENV{GIT_EXEC_PATH} = "/usr/libexec/git-core";

以上の全てを満たしておかないと、クライアントからgitolite-adminをcloneしようとした時に下記のエラーが出る。
$ git clone GITUSER@SERVERNAME:gitolite-admin
Cloning into 'gitolite-admin'...
Warning: No xauth data; using fake authentication data for X11 forwarding.
Assertion failed: (argv0_path), function system_path, file exec_cmd.c, line 30.
error: git-shell died of signal 6
fatal: The remote end hung up unexpectedly

特に上記ポイントの3番目は忘れがちなので注意が必要だ。

2012年2月25日土曜日

AndroidとMacをBluetoothのSPPで接続してデータ送受信

AndroidのサンプルコードにBluetoothChatというものがある。
これを改造してMacと繋いで文字列を送受信したので手順を書いておく。

EclipseでBluetoothChatのプロジェクトを作り、BluetoothChatからサンプルコード一式を取ってきて追加する。

BluetoothChatService.javaのUUIDを次のように変更する。
private static final UUID   MY_UUID_SECURE = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

今回、BluetoothChatService.javaのInsecureと書いてある部分は使わないので、メンバ変数から、MY_UUID_INSECUREとmInsecureAcceptThreadを削除する。この状態でビルドするとエラーが出るので、そのエラーに関連する部分もまとめて削除する。
さらにBluetoothChat.javaやリソースXMLの方も、insecureと書いてある部分は使わないので削除してよい。

この状態でビルドしたものをインストールして起動後、メニューボタンを押してMake discoverableを選んでMacから接続しておく。

接続が出来ていれば、Mac側に/dev/tty.NexusOne-BluetoothChatのようなデバイスファイルが出来ているはずだ。
ここまで出来たら、シリアルコンソールで接続する。
例えばscreenを使うなら以下のようにする。
sudo screen /dev/tty.NexusOne-BluetoothChat 9600

双方から文字列をやり取り出来れば完了だ。

Tips
図1のエラーが出る場合は、Mac側から設定を削除した後にもう一度最初から接続設定をするとうまくいくかもしれない。または図2および図3のようにBluetoothの設定画面を開いて、プロトコルを現在RS-232Cが設定されていたらモデムに、モデムならRS-232Cに設定して適用するとうまくいくかもしれない。


図1

図2

図3

参考にしたサイト
BluetoothChatでシリアル接続(SPP)を行う
Androidアプリ開発 ~Bluetooth SPP による無線通信~

2011年12月31日土曜日

phpのデバッグ

php.iniでエラー表示がOff(下記)になっている環境でデバッグする場合。
display_errors = Off
スクリプトに、ini_set( 'display_errors', 1 ); と書く。
<?
ini_set( 'display_errors', 1 );
...何らかの処理....
?>
そうしておいてテストすると、こんな風にエラーが表示される。
php -f foo.php

Fatal error: Call to undefined function bar() in /home/como/foo.php on line 15
リリース版では元に戻すのを忘れずに。

2011年12月29日木曜日

Lion ServerでのApache設定

Mac OSX Lion ServerのWebサーバのDocumentRootは、
/Library/Server/Web/Data/Sites/Default/
設定ファイルは、
/etc/apache2/sites/0000_any_80_.conf
システム環境設定→共有→Web共有→コンピュータのWebサイトフォルダを開く... からだと、
/Library/WebServer/Documents
が開かれてしまうので注意する。

2011年12月27日火曜日

NodeでWebSocket

2011/12/27現在NodeでWebSocketを使うなら、WebSocket-Nodeがベストなようだ。
ブラウザサポートが幅広い。

proxy環境内からnpm

npmでnodeにパッケージを追加しようとしたらエラー発生。
対策はこちら。
npm config set registry http://registry.npmjs.org/

先人の知恵に感謝。 proxy環境でnpm使おうとしたら、Error: socket hang up

2011年8月9日火曜日

vimdiffは忘れやすい

たまにしか使わないのでいつも忘れてしまう。
とりあえずdoとdpの使い方さえマスター出来れば、マージ作業の速度は10倍ぐらいに上がるはず。

起動
vimdiff file1 file2 [file3 [file4]]

起動 gvimの場合
gvim -d file1 file2 [file3 [file4]]

あるいは
alias gvimdiff='gvim -d' #もし無ければaliasを設定

gvimdiff file1 file2 [file3 [file4]]

前の差分へ移動
[c

次の差分へ移動
]c

現在のバッファをもう1つのバッファと同じくなるように変更をする
"o" は "obtain"の意味 (via :h vimdiff)
do

もう1つのバッファを現在のバッファと同じくなるように変更する
"p"何だろう?"put"のp?
dp

2011年6月3日金曜日

デュアルブートをシングルブートにしてパーティションサイズを広げる方法

WindowsとUbuntuのデュアルブートにしていたPCから、Windowsを削除してUbuntuのみシングルブートにした時のやり方。

ゴール
プライマリパーティションのWindowsを削除する
拡張パーティションのUbuntuをプライマリパーティションに移動する
拡張パーティションを削除する
プライマリパーティションを目一杯大きく取る

前提条件
プライマリパーティションが拡張パーティションよりも容量が大きいこと。
そうでない場合は、一時退避用に外部のストレージを用意する必要がある。

手順

  1. UbuntuのLiveCDを用意する

  2. 1のLiveCDでブートする

  3. 一時転送

  4. ddrescueを入れて、パーティションのクローンを作る
  5. ここらへんを参考に。
  6. GPartedをインストールする

  7. GPartedで転送先のパーティションをチェックする

  8. GPartedで不要となる拡張パーティションを削除し、プライマリパーティションを広げる

  9. 拡張パーティションにSwap領域を確保してマウントしている場合、swapoffする必要があるかも。
  10. Grubをインストールしなおす
  11. ここらへんを参考に。
  12. 再起動する
  13. 再インストールしたGrubによって、新しいパーティションのUbuntuで起動。


転送先の容量を間違えて転送元よりも小さなものを使ってしまい、クローン作成に失敗してはまった。

数百GBあるとかなり時間がかかるので、暇なときにやるとよいでしょう。

2011年5月29日日曜日

git-upload-pack: not found のとき

自分でgitをインストールしたサーバーにレポジトリを作って、ローカルからgit+sshでcloneしたら怒られた。そんな時の対策。

現象
$ git clone ssh://username@server/~/myrepo.git
bash: git-upload-pack: command not found
fatal: The remote end hung up unexpectedly

サーバーにログインして確認してみると、git-upload-packへのパスはちゃんと通っている。
$ which git-upload-pack
/home/username/local/bin/git-upload-pack

なぜ?
それは、ssh経由でログインした場合、PATHを.bashrcに設定したとしても読み込まれないのが原因。

対策A
--upload-packオプションで毎回指定する

git clone --upload-pack=/home/username/local/bin/git-upload-pack ssh://username@server/~/myrepo.git


対策B
git-configでサーバーのgit-upload-packのパスをconfigに書きこむ
git config remote.origin.uploadpack /home/username/local/bin/git-upload-pack

2011年5月22日日曜日

さくらのスタンダードプランでWebSocket

さくらインターネットのスタンダードプランで、WebSocketサーバーを実行してみたらうまく行った、という話。

使う物
  1. Ruby 最新版でいいだろう。

  2. RubyGems これも最新版でいいだろう。

  3. rev-websocket



手順
  1. node.jsのインストール → 失敗
  2. 定番WebSocketサーバーのnode.jsはport絡みのファイルの書き込み権限の問題で断念。
    きっとVPSならそんな心配はないのだろう。
  3. ローカルへのRubyのインストール

  4. $ wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p180.tar.bz2
    $ tar jxvf ruby-1.9.2-p180.tar.bz2
    $ cd ruby-1.9.2-p180
    ホームディレクトリ直下のlocalにインストールする。
    $ ./configure --prefix=$HOME/local
    $ make
    $ make install

  5. インストールしたRubyへのパスを設定する

  6. .bash_profile(.bashrc派の人もいるかな)に以下を記述
    前略
    export PATH=$HOME/local/bin:$PATH

    $ . .bash_profile

  7. RubyGemsをインストール

  8. $ wget http://rubyforge.org/frs/download.php/74886/rubygems-1.8.3.tgz
    $ tar zxvf rubygems-1.8.3.tgz
    $ cd rubygems-1.8.3
    $ ruby setup.rb

  9. rev-websocketをインストール

  10. $ gem install rev-websocket


    以下は動作テスト。

  11. rev-websocketのサンプルを~/wwwにコピー

  12. $ cp -r ~/local/lib/ruby/gems/1.9.1/gems/rev-websocket-0.1.3/examples/public ~/www
    $ cd ~/www/public

    エディタでecho.htmlを開く
    WS_URL = "ws://localhost:8081"; を WS_URL = "ws://サーバーのホスト名:8081"; に修正

  13. rev-websocketのサンプルのechoサーバーを起動

  14. $ ruby ~/local/lib/ruby/gems/1.9.1/gems/rev-websocket-0.1.3/examples/echo.rb
    start on 0.0.0.0:8081

  15. Webブラウザーでrev-websocketのサンプルにアクセス

  16. http://ホスト名/public/echo.html
    こんな表示が出ればOKだ。
    server: Hello, world!
    client: hello
    Sun May 22 2011 09:41:40 GMT+0900 (JST)connecting to ws://ホスト名:8081...
    Sun May 22 2011 09:41:40 GMT+0900 (JST)connected.
    Sun May 22 2011 09:41:40 GMT+0900 (JST)message sent: client: hello
    Sun May 22 2011 09:41:40 GMT+0900 (JST)message received: server: Hello, world!
    Sun May 22 2011 09:41:40 GMT+0900 (JST)message received: client: hello
    Sun May 22 2011 10:17:32 GMT+0900 (JST)disconnected...


さて、何を作ろうか?