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を使うのがいいかと思います。

by typester / at 2011-01-04T10:30:00 / perl · osx / Comment

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から削除するつもりです。

by typester / at 2011-01-04T10:25:00 / perl · anyevent · osx / Comment

ふるいPerlをいれる

perlbrew を導入したのでもりもりテスト環境を作れるようになったわけですが、perl-5.8.8 をいれようとしたら

    Can't open makefile: No such file or directory.
    Can't open x2p/makefile: No such file or directory.
    make: *** No rule to make target `<command-line>', needed by `miniperlmain.o'.  Stop.
    make: *** No rule to make target `<command-line>', needed by `miniperlmain.o'.  Stop.

のように make がこけてしまってインストールできなかった。 ググってみるとどうも新しいgccだと古いPerlはうまくビルドできないらしい。

解決法としては makefile (OSXではGNUmakefile) の command-line を含む行は消してあげるというのでなんとかなるみたい。

以下のようにしてみた:

$ ./Configure -de -Dprefix=$HOME/perl5/perlbrew/perls/5.8.8
$ perl -i~ -nle 'print unless /command-line/' GNUmakefile x2p/GNUmakefile
$ make
$ make test
$ make install

これでちゃんとperlbrewからも認識できてて

$ perlbrew switch 5.8.8

とかでswitchできました。まる。

by typester / at 2010-08-13T09:05:00 / osx · perl / Comment

ユニバーサルバイナリ作成用シェルスクリプト

iPhone用にビルドしたライブラリは実機用(armv6/armv7)とシミュレータ用(i386)のユニバーサルバイナリとして作成しておくと使い勝手が良いです。 その分ビルドは面倒になるのですが。。

僕は通常以下のようにしてユニバーサルバイナリを作成してます。

  1. まずprefixをそれぞれ ~/dev/iphone/lib/curl-7.20.1-armv6 ~/dev/iphone/lib/curl-7.20.1-armv7 ~/dev/iphone/lib/curl-7.20.1-i386 などとしてそれぞれのアーキテクチャ用にビルドをする
  2. 適当に書いた bundle.sh でユニバーサルバイナリ化

この bundle.sh は上の例だと

./bundle.sh ~/dev/iphone/lib/curl-7.20.1

として実行すると ~/dev/iphone/lib/curl-7.20.1-armv6 ~/dev/iphone/lib/curl-7.20.1-armv7 ~/dev/iphone/lib/curl-7.20.1-i386 が全部がっちゃんこした ~/dev/iphone/lib/curl-7.20.1 ができるという寸法です。

この方法だとまだ3つ分手動でビルドするのがめんどくさいので、そこも自動化したいところですね。

by typester / at 2010-07-27T14:52:00 / osx · iphone / Comment

ライブラリをユニバーサルバイナリでインストールする

以下のサイトが詳しい

http://macwiki.sourceforge.jp/wiki/index.php/UniversalBinary

Imager に必要な libjpeg などをユニバーサルバイナリにしてみた時のメモ

-M などがついていて -arch が複数指定できない場合以外は

CFLAGS='-arch x86_64 -arch i386 -isysroot /Developer/SDKs/MacOSX10.6.sdk' CXXFLAGS=$CFLAGS

とかすればいいということだが、libjpeg-M られていて無理だったので、amd64 と i386 という二つのディレクトリにソースコードを展開、それぞれ以下のオプションで make まで終わらす:

$ cd amd64
$ CFLAGS='-arch x86_64 -isysroot /Developer/SDKs/MacOSX10.6.sdk' CXXFLAGS=$CFLAGS ./configure ...
$ make

$ cd ../i386
$ CFLAGS='-arch i386 -isysroot /Developer/SDKs/MacOSX10.6.sdk' CXXFLAGS=$CFLAGS ./configure ...
$ make

make されてできたバイナリを lipo コマンドでユニバーサルバイナリ化する。 上記サイトを参考にして、

#!/bin/sh

filelist=$(find ./amd64 -type f |grep -v \\.o$ | xargs file | sed -e 's,^\./amd64/,,g' | \
               grep -E \(Mach-O\)\|\(ar\ archive\) |sed -e 's,:.*,,g' -e '/\for\ architecture/d')

for i in $filelist
do
    echo $i
    /usr/bin/lipo -create amd64/$i i386/$i -output `basename $i`
    mv -f `basename $i` amd64/$i
done

このようなスクリプトを書いて、amd64 などのディレクトリの一つ上の階層で実行すると、amd64 ディレクトリのバイナリがユニバーサルバイナリ化されるという仕組みを作ってみた。

その後、amd64 のほうで make install してやれば OK。

by typester / at 2010-01-08T11:28:00 / osx / Comment

Snow Leopard の Perl とアーキテクチャ

Snow Leopard には二つの Perl がインストールされている

  • /usr/bin/perl5.10.0
  • /usr/bin/perl5.8.9

デフォルトの /usr/bin/perl は 5.10.0 のほう。それぞれユニバーサルバイナリになっていて、

$ file /usr/bin/perl5.10.0
/usr/bin/perl5.10.0: Mach-O universal binary with 3 architectures
/usr/bin/perl5.10.0 (for architecture x86_64):  Mach-O 64-bit executable x86_64
/usr/bin/perl5.10.0 (for architecture i386):    Mach-O executable i386
/usr/bin/perl5.10.0 (for architecture ppc7400): Mach-O executable ppc

$ file /usr/bin/perl5.8.9
/usr/bin/perl5.8.9: Mach-O universal binary with 2 architectures
/usr/bin/perl5.8.9 (for architecture i386):     Mach-O executable i386
/usr/bin/perl5.8.9 (for architecture ppc7400):  Mach-O executable ppc

という感じで、5.10 は 64bit 版があるが、5.8 にはない。

で、普通に perl を実行すると perl5.10.0 は x86_64 で実行され、perl5.8.9 は i386 で実行される。

このアーキテクチャの差が結構くせ者で Snow Leopard 上で普通にライブラリなどを make すると x86_64 だけでビルドされてしまうため、そのようにして作ったライブラリはそのままでは perl5.8.9 からは使えないということになる。

デフォルトの 5.10.0 だけ使っている分にはなにも問題はないのだが、残念なことにこの 5.10.0 というのはいろいろな問題があり、開発に使用することはおすすめできない状況。(せめて 5.10.1 にしてくれればいいのに)

したがって無用なトラブルを避けるためにも 5.8.9 の方を使用するか、自前でビルドした perl を使用するのが良い。

またこのように x86_64i386 両方のアーキテクチャの実行ファイルがあり得る Snow Leopard に対して自分でライブラリをインストールする場合それらもユニバーサルバイナリにしておくと良い。

念のため追記@2010-01-08T15:19:23+09:00: もちろんこれは 64bit 対応の CPU の場合の話。そうでない場合はどちらも i386 で実行されるのでこの問題は起こらない。

by typester / at 2010-01-08T10:51:00 / osx · perl / Comment

CocoaEmacsその後

フルスクリーン化以外にもいじりたくなったのでそれぞれブランチを切った。

という感じになっています。 master はこれらの統合ブランチになってますので使ってる人いたら注意です。

使いながらちょいちょいいじっていて、昨日からの更新としては

  • フルスクリーン時に裏にノーマルなウィンドウが残ってしまっていたのを修正
  • 日本語入力時に Shift なんちゃらが IME をとおらずそのまま Emacs に渡されてしまっているのを修正

という感じになっております。

by typester / at 2009-12-18T13:03:00 / emacs · osx / Comment

CocoaEmacsのフォント設定

現状こんな感じ。以前書いたCarbonEmacsの設定と大して変わってない。unicode コードセットで表示される文字が増えていたのでそれに対応した程度。

(create-fontset-from-fontset-spec
 (concat
  "-*-fixed-medium-r-normal--12-*-*-*-*-*-fontset-tobi"
  ",ascii:-apple-codingfonttobi-medium-r-normal--16-120-72-72-m-120-*-*"
  ",japanese-jisx0208:-apple-osaka-*"
  ",katakana-jisx0201:-apple-osaka-*"
  ",unicode:-apple-osaka-*"
  ",chinese-big5-1:-apple-apple ligothic medium-*"
  ))

(set-default-font "fontset-tobi")

ascii 用につかってる CodingFontTobi は proggyfonts.com から。

もちろんビットマップ表示にするため

$ defaults write org.gnu.Emacs AppleAntiAliasingThreshold 16

としている。

(setq mac-allow-anti-aliasing nil)

は Snow Leopard では効かないみたいだ。

by typester / at 2009-12-17T23:50:00 / emacs · osx / Comment

フルスクリーン Cocoa Emacs

emacs23 が正式にリリースされ、ちまたではウィンドウシステムが Cocoa になったぞ、とか 64bit 対応だぞ、とか multitty だぞ、と盛り上がっていますが、 個人的にほとんど興味のないまま今日まできました。というのも CocoaEmacs はフルスクリーンにできないという僕にとっては致命的な問題があったからです。

というのも最近は Emacs をフルスクリーンにし縦二分割で使ういわゆる imakado スタイルを実践しているため、それができない CocoaEmacs は眼中になかったのでした。

そんなわけでずっと CarbonEmacs を使ってきたのですが、 Snow Leopard に移行したのを機に CocoaEmacs に移行し、さらについでにフルスクリーン化できるようにしてみています。 github でやってます。

typester's emacs at master - GitHub

現状でも若干不具合がありますが、使える段階にはなっていると思います。

ビルドは

$ git clone git://github.com/typester/emacs.git
$ cd emacs
$ ./configure --with-ns
$ make bootstrap
$ make install

こんな感じにすると、nextstep ディレクトリ以下に Emacs.app ができます。フルスクリーンにするには

M-x ns-toggle-fullscreen

でいけます。キー割り当てておくと便利です。

対応環境は定かではありませんが、OS X 10.4 と 10.6 で動作確認しております。

また 10.6 の場合のみ、フルスクリーン時に隠れているメニューバーや Dock 領域にマウスカーソルを移動させると自動的に表示されるようになっています。 CarbonEmacs と違い Dock も自動で表示されるので個人的に非常に便利です。10.6 からの新 API のため、10.5 以前ではフルスクリーン時にメニューバー、Dock は強制オフになります。

既知の不具合として外部ウィンドウでフルスクリーン化して戻そうとすると落ちるというのが報告されており調査中です。 それ以外は便利に使用できています。この文章もフルスクリーン CocoaEmacs で書いています ;)

またこのハックをしたことで elisp から C や Objective-C のコードを呼ぶ方法がわかったのでいろいろ夢がひろがりんぐというところです。

by typester / at 2009-12-17T20:27:00 / emacs · osx / Comment

無線APによって自動でhostsを変える方法

OSX の LaunchAgents には特定のパスを監視して更新があったらプログラムを起動すると言うことが出来ます。例えば以下のような設定を書いてみると:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
          "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>org.unknownplace.wifi_switch</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/bin/zsh</string>
      <string>-c</string>
      <string>exec perl /Users/typester/dev/scratch/wifi_switch/switch.pl</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/dev/null</string><!-- <string>/tmp/error</string> -->
    <key>StandardOutPath</key>
    <string>/dev/null</string>
    <key>WatchPaths</key>
    <array>
      <string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
    </array>
  </dict>
</plist>

/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist を監視しそれが更新されたら /Users/typester/dev/scratch/wifi_switch/switch.pl を実行する。と言うことが実現できます。

この監視先のファイルは OSX の無線ネットワーク設定なので、これが更新されると言うことは無線通信の状態が変わったときと言うことを意味します。

これを有効にするにはこのファイルを適当な名前 hoge.plist/System/Library/LaunchDaemons/ 保存すれば次回起動から有効になります。すぐに有効にしたい場合は、

sudo launchctl load /System/Library/LaunchDaemons/hoge.plist

などとすればOKです。詳しくは launchctl や LaunchAgent/LaunchDaemon のドキュメントを参照のこと。システムレベルの LaunchDaemon を使用しているのは /etc/hosts を書き換えるのに root 権限が必要だからです。

あとはここで起動されるスクリプト中でからAPの情報を取得しそれをもとに hosts を書き換えればいいわけです。APの情報は

/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I

と言うコマンドで取得可能なのでそれをパースすればオッケーです。

以下に僕が実際に使用しているスクリプトを貼っておきます。

http://gist.github.com/247950

このスクリプトと同じところに、default.mt特定のAPのSSID名.mt と言うファイルで hosts を書いておくと、通常は default.mt/etc/hosts に書き出され、SSIDにマッチするファイルがある場合には SSID名.mt/etc/hosts に書き出されるという感じです。

AP によって hosts を変えたいという状況がそんなにあるとは思いませんが、ネットワークの状態によっていろいろ設定を変えると言う目的では便利で使えますので覚えておいて損はないでしょう。

by typester / at 2009-12-03T16:00:00 / osx / Comment

1 2 3 4 5

(Page 3 of 5)