Cocoa::EventLoop
そういえば Cocoa::EventLoop と言うモジュールを書いたんでした。
これはもともと AnyEvent::Impl::NSRunLoop として書いていたイベントループ処理部分だけを単体モジュールとして切り出した物で、 AnyEvent を使わなくても Cocoa のイベントループを Perl から使用できるというものです。
くわしくはドキュメントを参照してもらうとして、Cocoa::Growl を使ったサンプルを載せてみます:
use Cocoa::EventLoop;
use Cocoa::Growl;
my $done = 0;
growl_notify(
name => 'Notification Name',
title => 'Hello',
description => 'Cocoa World!',
on_click => sub {
$done++;
},
on_timeout => sub {
$done++;
},
);
Cocoa::EventLoop->run_while(0.1) while !$done;
これを AnyEvent で書くと:
use AnyEvent 5.30;
use Cocoa::EventLoop;
use Cocoa::Growl;
my $cv = AnyEvent->condvar;
growl_notify(
name => 'Notification Name',
title => 'Hello',
description => 'Cocoa World!',
on_click => sub {
$cv->send;
},
on_timeout => sub {
$cv->send;
},
);
$cv->recv;
ほぼ一緒ですね。 また、この例ではわからないですがtimerやioのインタフェースもAnyEventに合わせてあるのでほとんど同じ感じで使うことができます。
ただまぁ、AnyEventには豊富なライブラリがあるため、上記のGrowlのサンプル以上に複雑なことをする場合は素直にAnyEventを使うのがいいかと思います。
AnyEvent 5.3 Released
出てました。気がつきませんでした。
このバージョンから AnyEvent::Impl::Cocoa が入りました。これは Cocoa::EventLoop を AnyEvent から使うアダプターで、
use Cocoa::EventLoop;
していると自動的に使われます。したがって、
use AnyEvent;
use Cocoa::EventLoop;
# AnyEventを使用したコード...
と言うように書くと自動的に Cocoa のイベントループで AnyEvent が動作するというわけです。 こうしておけば Cocoa::Growl など、Cocoa::EventLoop を必要とするモジュールをシームレスに AnyEvent 内で使うことが出来て便利です。
なお、AnyEvent::Impl::NSRunLoop は DEPRECATED ってことでとりあえずドキュメントに注意書きを加え、さらに数週間後にはCPANから削除するつもりです。
PerlのXSでObjective-Cを使うときに気をつけること
QuickDraw API で定義されている Move
マクロが、perl の handy.h の中で定義されているものとコンフリクトするため、
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
// undefine Move macro, this is conflict to Mac OS X QuickDraw API.
#undef Move
#import <Foundation/Foundation.h>
こんなようにしてperl関係のヘッダーをincludeしたあと#undef
してあげたうえでCocoaのヘッダーをimportするようにすると良い。
なお、 Foundation 以外にリンクするときはまた別の問題があるかもしれない。
基本XS使うときは、まず単体でうごくCやObjective-Cのコードを書いて、XSはそれをつなぐだけという感じで使っているので、ガチでXS内でごりごり処理を実装することはなく、perlのMoveマクロは使ったことないから、それを使いたいときにどうすればいいかは知らない。
memmoveのラッパーみたいだけど、NewxやSafefreeなどのようにこれ使ったほうが良いとかたぶんあるんだろうけど。
AnyEvent::Impl::NSRunLoop
っていう頭おかしいモジュールを作ってるんですが、これについていくつか schmorp (AnyEvent作者)とはなして以下のようにしていくことにした。
- NSRunLoop の実装は Cocoa::RunLoop と言うモジュールに外だし
- AE::Impl の方はそれをただ使うだけ
- Cocoa::RunLoop は AnyEvent に依存しなくても使える
- AnyEvent は Cocoa::RunLoop がロードされている環境ではバックエンドに Impl::NSRunLoop をつかう
と言うわけで将来的には、Cocoa::Growl とかそれ系のモジュールはシームレスに AnyEvent 内で使えるようになる感じです。
kAudioSessionCategory_PlayAndRecord のときの AudioRoute 文字列メモ
ドキュメントに載ってなくて、実際うごかしてみて文字列を知るという状況。 なので持ってない機種とかデバイスでどうなるのかわからないという問題があり不安。
ReceiverAndMicrophone
PlayAndRecord 時は iPhone ではデフォルトでこれになる模様。 通常のスピーカーではなく電話の受話口から音が出る。
HeadphonesAndMicrophone
ヘッドフォンさしたとき。
SpeakerAndMicrophone
iPad とか(たぶん最新以外のiPod Touchも)のように受話口がない端末ではこれがデフォルトっぽい。
デフォルト以外のルートに設定する
スピーカーに強制的に変更するには AudioSessionSetProperty
でできる。
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty(
kAudioSessionProperty_OverrideAudioRoute,
sizeof (audioRouteOverride),
&audioRouteOverride
);
他のルートに変更する方法は undocumented。
ただこのうわがきはすでに SpeakerAndMicrophone なところで実行するとおかしくなっちゃう。 AudioSessionSetProperty
するまえに AudioSessionGetProperty
で現在の値を確認するようにすること。
あと、AudioRoute の変更は AudioSessionAddPropertyListener
で kAudioSessionProperty_AudioRouteChange
を登録しておけば監視できる。
CCRepeatForever は CCSequence の中では使えない
やろうとしたら BAD_ACCESS になった。
prog_guide:actions_composition - cocos2d for iPhone
IMPORTANT: CCRepeatForever is not a valid CCIntervalAction. You can't use a CCRepeatForever inside a CCSequence action.
らしい。
導入アニメしたあと、ループさせたいような場合はよくあるからこれできないと不便なきもする。
そう言うことがしたい場合は CCCallFunc
でアニメーションの終了をもらいそこで CCRepeatForever
する。CCCallBlock
っていう Blocks インタフェースあるからそれ使えばメソッド増やさなくてもいいようだ。
ブログ
clmemo になんか記事っぽくメモを書くのに疲れてきたので、ブログを復活させようそうしよう。
昔のエントリ見るとちゃんとメモっぽいのだけどなんでだろうなーw
cocos2d の Spritesheet の Retina 対応
cocos2d ではメモリ効率よく画像リソースをあつかうために以下のような CSS Sprite っぽい画像に複数リソースを格納して使うことができる。
cocos2d 自体は 0.99.5 から Retina 対応するようで、通常の画像ファイルなら -hd.png
のような suffix で画像を置いておけば自動的にそいつが使われるようになった。
スプライトシートでの対応方法が見つけられなかったので、いろいろ試してみた。
結論から書くと、
- time_num.png
- time_num-hd.png
- time_num.plist
- time_num-hd.plist
とそれぞれファイルを作成する。plist のなかのファイル名は -hd
ありなしに関わらずどちらもおなじ物を指定する必要がある。
そのうえで、
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"time_num.plist"];
CCSpriteBatchNode* time_num = [CCSpriteBatchNode batchNodeWithFile:@"time_num.png"];
[self addChild:time_num];
CCSprite* time = [CCSprite spriteWithSpriteFrameName:@"time_num1.png"];
time.position = ccp(160, 240);
[self addChild:time];
などとすればいいようだ。座標系をただ倍にすればいいような単純な高解像度画像のためにもわざわざ別途plistを用意してあげなければいけないのが若干めんどくさい。
plist 作成が面倒な場合、
CCTexture2D* texture = [[CCTextureCache sharedTextureCache] addImage:@"time_num.png"];
CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:CGRectMake(0, 0, 10, 14)];
というような感じでテクスチャを自前で切り出して使うことも可能のようだが、こっちのほうがコードが煩雑になりそう。
(0.99.5-rc1 でためしてます)
VAIO P に ubuntu 10.4 入れたときのメモ
だいぶん前の話になりますが、重たい Macbook を常に持ち歩くのに嫌気がさし、外出用PCとして VAIO P を購入しました。 ただ Windows をつかうつもりは全くなかったので、とどいてすぐ ubuntu をインストールしました。
リカバリディスクの作成
最近の PC はリカバリディスクがないかわりに、HDD 内にリカバリ領域をもつ。 この領域もフルで使いたかったのでまずリカバリディスクを作成しリカバリ領域が消えても問題ないようにする。
手順はマニュアルを参照してやるとすぐできた。 なんとこれにDVD-Rが二枚必要だった。
ubuntu インストール
10.4 の NetBook エディションを選択。(当時は 10.10 がまだ出ていなかった)
インストールはイメージを DVD に焼いて DVD ブートし、通常インストール。
まず DVD ブートの方法がわからず苦労する。 起動時に適当にボタンを押しまくって F2 で BIOS 画面が出せることがわかった。そこで起動順序を変更すれば OK。(なんかこれマニュアルに見つけられなかった)
あとスティックが効かないのでGUIインストールは苦労。 これはあとで以下の起動オプションを渡せばいいことがわかった。
i8042.reset i8042.nomux i8042.nopnp i8042.noloop
あとは手順通りにインストール。HDD パーティションは 10GB くらいを /
に、残りを全部 /home
に割り当てた。swap 領域はなしとした。
スティックポインタが動くよう修正
インストール完了したらまずスティックポインタを動くように修正する。/etc/default/grub
の GRUB_CMDLINE_LINUX_DEFAULT
にさっきの
i8042.reset i8042.nomux i8042.nopnp i8042.noloop
を追加。これで再起動すればスティックが動くようになる。
SSD 対策
意味あるかわからないけど fstab をいじって、/
、/home
ともに noatime でマウントするように、/tmp
は tmpfs に設定しておく。
ディスプレイドライバ
デフォルトだと描画が重たいので GMA500 用のドライバを入れる
sudo add-apt-repository ppa:gma500/ppa
sudo apt-get update
sudo apt-get install poulsbo-driver-2d poulsbo-driver-3d poulsbo-config
また、/etc/default/grub
の GRUB_CMDLINE_LINUX_DEFAULT
にさらに
mem=1920mb nohz=off
を追加しておく。
この辺の情報は ubuntu の wiki の HardwareSupportComponentsVideoCardsPoulsbo にまとまってる。
で、これはしばらくつかった最近はまったのだが、このドライバはカーネルアップグレードしても自動的にビルドされないみたいでうっかりアップデートがきてカーネルのバージョンをアップしちゃうと起動不可能になってしまう。カーネルアップしたら再起動するまえにこのドライバの再インストールを忘れないようにする必要があるようだ。
サスペンドできるように
ここの方法を今は使っている http://ubuntuforums.org/showthread.php?t=1531976
sudo apt-get uninstall vbetool
sudo apt-get install uswsusp
して、/usr/sbin/pm-suspend
を以下で上書き
#!/bin/sh
#remove wlan modules
for m in `lsmod | grep ath9k | awk '{print $1}'` ;
do
rmmod $m
done
s2ram --force
modprobe ath9k
日本語入力できるように
- ibus-anthyとかいれる
- System -> iBus Preferences で anthy を Input Method リストに入れる
- System -> Language Support で Keyboard input method system を ibus にセットして再起動
でOK。
日本語入力のトグルキーは iBus Preferences から変更できる。デフォルトでは Ctrl-space もトグルキーとして設定されているが、これは emacs とコンフリクトするからはずしておく。
残ってる問題
スピーカーから音が出ない。ヘッドホン端子につなげばそこから音は出る。 解決方法知っている人いたら教えてください。
使用感
ターミナルとブラウザ、あとたまにSkypeつかうっていう程度なので ubuntu でも全然問題ない、というか非常に快適。
キーボードはこの大きさでも普通にタッチタイプでき、ローカルに入った Emacs でその気になればコーディングも可能。
またいまや Google Chrome のおかげでほかの OS と遜色ないブラウザ環境があるのも大きい。Flash Player も Chrome 自身に内蔵されているので何も考えなくていい。 Flash 内で日本語がインライン入力できるあたりは OS X より快適とも言える。
外出時にWiFiつないだりといったネットワーク設定なんかも当たり前のようにタスクトレイからできてLinuxも楽ちんになったものだなー。