2016年7月13日水曜日

Setting a Debian Console Font

Debian のコンソールフォントを変更するには。

sudo dpkg-reconfigure -plow console-setup


2016年4月29日金曜日

The Debian Alternatives System

Debian には同一あるいは類似の機能を持つプログラムをひとつのシステムに同時にインストールして、共存させる仕組みがある。それが Debian Alternatives system です。これらのプログラムを管理するコマンドが update-alternatives コマンド。


Debian のパッケージ管理コマンドについて

Debian 管理者ハンドブック 5.4 Note dpkg か? apt か?
dpkg はシステムツール (バックエンド)、apt はユーザに近いツールとみなすべきです。apt は dpkg の制限を克服しています。これらのツールは互いに協力して作業を行います。両者は互いに異なる得意分野を持っており、それぞれが特定の作業を担当しています。

APT は巨大なプロジェクトで、当初の予定ではグラフィカルインターフェースを含んでいました。APT はライブラリに基づいており、そのライブラリにはコアアプリケーションが含まれています。apt-get は最初のコマンドラインベースフロントエンドで、APT プロジェクト内で開発されました。apt は APT から提供されているもう一つのコマンドラインベースフロントエンドで、apt-get の持っていた設計上のミスを克服しています。
APT の数多くのグラフィカルインターフェースは外部プロジェクトとして生まれました。たとえば synaptic、aptitude (テキストとグラフィカルモードインターフェースの両方があり、グラフィカルモードインターフェースはまだ完成していません)、wajig などが生まれました。最も推奨されるインターフェースは apt で、この節では apt を例に使います。apt のコマンドライン構文と apt-get や aptitude のコマンドライン構文はよく似ていることに注意してください。apt、apt-get、aptitude の間に大きな違いがある場合は、その違いを詳しく述べます。

APT は C++ プログラムで、libapt-pkg 共有ライブラリがその機能の多くを担っています。共有ライブラリを使うとユーザインターフェース (フロントエンド) の作成が楽になります。なぜなら、ライブラリに含まれるコードは簡単に再利用できるからです。歴史的に言って、apt-get は libapt-pkg のテスト用フロントエンドとして設計されましたが、成功を収めたためにその事実は曖昧にされがちです。


なるほど。コマンドラインベースのフロントエンドとしては apt を推奨しているようです。その他、管理者のために設計された対話型の準グラフィカルモードを備えた aptitude を使用するのも apt-get よりかはずっと合理的(6.4.1)とあるので、apt もしくは aptitude がよいようです。

Debian に Node.js

Debian(8.4.0)に Node.js をインストールする際の少しややっこしい話。apt コマンドを使ってインストールするとコマンド名が通常 node となるところnodejs になる。いろいろめんどうになるとののことなのでこれを変更する。

VirtualBox に Debian インストール後 sudo をインストールしてユーザを sudo グループに追加してあります。そして Node.js のインストール。

sudo apt update
sudo apt install Node.js

確認のため dpkg に L オプションをつけて表示してみる。

dpkg -L nodejs

インストール先一覧が出ると思います。バイナリは /usr/bin/nodejs であることがわかります。これを一般的な node コマンドとして使用するために update-alternatives を使用して設定してやります。

sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10

成功すればその旨のメッセージがでます。

2015年2月7日土曜日

JavaScript for Automation Release Note

OSXで作業を自動化するために AppleScript を使いますが Yosemite からは JavaScript もサポートとされました。以下ドキュメントです。

<https://developer.apple.com/library/mac/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/index.html>


2014年11月15日土曜日

Master for iTunes Droplet を Yosemite で使う

OS X 10.10 で Master for iTunes Droplet を使うときの注意。

https://discussions.apple.com/message/27014610#27014610

ドロップレットのスクリプト にバージョンのミスマッチがあるよ、との指摘です。ご指摘の通りに書き直す。適当にコピーを作ってとおっしゃっていますが、僕は直接書き換えました。

  1. Master for iTunes Droplet -> パッケージの内容を表示
  2. Contents/Resources/Scripts/main.scpt をスクリプトエディタで開く
  3. 検索すると "10.6" が2箇所あるので両方 "10.10" に書き換えて保存する

以上。

2014年11月2日日曜日

起動可能な OS X インストーラを OS X Mavericks で作成する

Yosemite にアップデートする前にいろいろの準備をする。タイトルの通り。Apple の説明によると以下のよう。

sudo /Applications/Install\ OS\ X\ Mavericks.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume --applicationpath /Applications/Install\ OS\ X\ Mavericks.app

Apple のリンク
http://support.apple.com/kb/HT5856?viewlocale=ja_JP

2014年10月9日木曜日

おおぅ

OS X 10.8 and later—Dispatch objects (including queues) are Objective-C objects, and are retained and released automatically.

こんなことになっていたのか。。。てっきり GCD のオブジェクトはCの構造体だと思っていました。試しに ARC を NO にしてみますと

[queue release];

が通ります。そして dispatch_release() も使えます。

2014年5月29日木曜日

NSTableView, NSCell-based or NSView-based

NSTableView がどんな場合に cell-based か view-based で作成されるべきかわからなかったのでメモ。

NSCell-Based Tables Are Still Supported
In OS X v10.6 and earlier, each table view cell was required to be a subclass of NSCell. This approach caused limitations when designing complex custom cells, often requiring you to write your own NSCell subclasses. Providing animation, such as progress views, was also extremely difficult. In this document these types of table views are referred to as NSCell-based table views. NSCell-based tables continue to be supported in OS X v10.7 and later, but they’re typically used only to support legacy code. In general, you should use NSView-based tables.

Although you use the same Interface Builder techniques to create both NSView-based and NSCell-based table views (and to add columns to a table), the code required to provide individual cells, populate the table view, and support programmatic editing differs depending on the table type. In addition, you use different Cocoa bindings techniques depending on whether you’re working with an NSView-based or NSCell-based table.
- Table View Programming Guide for Mac -

Mac OS X 10.6 とその以前のバージョンでは、各テーブルセルは NSCell のサブクラスである必要がありました。複雑なカスタムセルを設計する際に、独自の NSCell のサブクラスを記述しなければならないことがあり、このアプローチは限界をもたらしました。プログレスビュー(進捗状況を表示するビュー)のようなアニメーションを提供するときはまた、非常に困難でした。本ドキュメントではこのタイプのテーブルビューは セルベース(NSCell-based)のテーブルビューと呼びます。セルベースのテーブルは継続して、Mac OS X 10.7 とそれ以降でサポートされますが、典型的には従来のコードをサポートするためだけに使用われます。通常はビューベース(NSView-based)のテーブルを使用するべきです。

ビューベースとセルベースのテーブルビュー両方を作成(そしてテーブルにカラムを追加)するためにインターフェイスビルダーで同じ手法を用いますが、個々のセルを提供するために必要とされるコード、テーブルビューへのデータの格納、そしてプログラム的な編集のサポートは、テーブルのタイプに応じて異なります。加えて、ビューベースまたはセルベースのテーブルで作業しているかどうかに応じて、異った Cocoa バインディングの手法を用います。

Most Tables Are Based on NSView
Most tables are NSView based, which means that each cell is provided by an NSView subclass, often by NSTableCellView (or a subclass). Some tables are NSCell based, which means that each table cell is based on a subclass of NSCell. For the most part, NSCell-based tables are used to support legacy code; if you’re creating a new app, you want to use NSView-based tables. In this document, a table is assumed to be NSView based unless specified otherwise.
- Table View Programming Guide for Mac -

ほとんどのテーブルは NSView に基づいています。それは、それぞれのセルが NSView や、しばしば NSTableCellView(またはサブクラス)によって提供されることを意味します。いくつかのテーブルは NSCell に基づいていて、それぞれのテーブルセルが NSCell のサブクラスに基づいていることを意味します。ほとんどの場合、セルベースのテーブルは従来のコードをサポートするために使用されます。新たにアプリケーションを作成するならば、ビューベースのテーブルを使っていただきたい。本ドキュメントでは特に断りがない限り NSView に基づいたテーブルを仮定しています。

というわけで、レガシーコードをサポートするとき以外はビューベースで。



さらにテーブルのバインディングについてメモ。 同ドキュメントには "Populating a Table View Using Cocoa Bindings" でビューベースのテーブルのバインディングについての説明がある。以下まとめ。
  1. ArrayController に Content Array を設定する。(モデルオブジェクトの入った Array)
  2. テーブルビューの Content に ArrayController, arrangedObjects でバインドする
  3. TableCellView のサブビューにそれぞれ Table Cell View, objectValue.{property} でバインドする。

以上。セルベースのテーブルはカラムにバインドするとかなんとか。詳しくは "Creating Bindings for an NSCell-Based Table View" で。関係ないけど "populate"という単語はプログラム関係の翻訳では、データベースにデータを入れるという意味で使用される。移入する、とか格納するとか、投入するとか。

2014年5月23日金曜日

ポップアップメニュー

ボタンを押したらポップアップメニューが出るようにしたい。どうするか。
NSButton のサブクラスを作成して、NSView の

+ (NSMenu *)defaultMenu
- (NSMenu *)menuForEvent:(NSEvent *)theEvent

をオーバーライドしてもいいけど、サブクラスを作らない方法。

-----------------------------------------------------------
- (IBAction)buttonAction:(id)sender {
   
    NSMenu *menu = [[[NSMenu alloc] initWithTitle:@"MenueTitle"] autorelease];

    [menu addItemWithTitle:@"Test"
                    action:@selector(selectedItem:)
             keyEquivalent:@""];
   
    [NSMenu popUpContextMenu:menu
                   withEvent:[NSApp currentEvent]
                     forView:[[sender cell] controlView]];
   
    return;
}

- (void)selectedItem:(id)sender {
    NSLog(@"Selected:%@",sender);
}
-----------------------------------------------------------


2014年5月22日木曜日

self and super

 super
実行するメソッドの検索をコンパイラに伝える単なるフラグ。レシーバとしてのみ使用する。

 self
変数名。

以下 ”Objective-C プログラミング言語” によるサンプル。

 -----------------------------------------------------
+ (Rectangle *)rectangleOfColor:(NSColor *) color
{
    self = [[Rectangle alloc] init]; // BAD
    [self setColor:color];
    return self;
}
 -----------------------------------------------------
+ (id)rectangleOfColor:(NSColor *)color
{
    id newInstance = [[Rectangle alloc] init]; // GOOD
    [newInstance setColor:color];
    return newInstance;
}
 -----------------------------------------------------
+ (id)rectangleOfColor:(NSColor *)color
{
    id newInstance = [[self alloc] init]; // EXCELLENT
    [newInstance setColor:color];
    return newInstance;
}
 -----------------------------------------------------

悪い、良い、 最高の違いは、クラスメソッドがサブクラスからの呼び出しに対応しているかどうか。

2013年7月3日水曜日

To Implement 1D Cellular Automaton in Pure Data.


wikipedia の説明によりますと "最も単純だが自明ではないCAは、1次元で各セルは2つの状態をとることができ、近傍は両側に接している隣のセルという場合である。" そうです。 "自明ではない" としているところから、最も条件の少ない CA として証明はされていないのだろうと推測します。

さてさて、この場合、注目する中央1つのセルとその近傍の2つのセルのとれる状態は全部で 23= 8 通り。2つの状態をそれぞれ◆と◇で表現すると以下のよう。

◆◆◆◆◆◇◆◇◆◆◇◇◇◆◆◇◆◇◇◇◆◇◇◇

そして注目する中央のセルが近傍のセルの状態でどのように次の状態に移行するか、という規則を定めます。

◆◆◆◆◆◇◆◇◆◆◇◇◇◆◆◇◆◇◇◇◆◇◇◇

上の例では並びが◆◇◇, ◇◆◆, ◇◆◇, ◇◇◆のとき注目する中央のセルが◆にそれ以外は◇になります。とれる状態が2つであることから、これらを◆=1、◇=0 としてビットの並びに置き換えますと、

  111    110    101    100    011    010    001    000  
00011110

となり、規則が8ビット(0 から 255)で参照できるようになります。この例では 00011110 なので、十進で 30 と表現できます。規則の総数は 28 = 256 通りになります。


Pure Data での実装
 32 個のセルを用意し現在の状態(0 or 1)を Array に保存しています。セルの両端はつながっているもの(..., 31, 0, 1, 2, 3, ..., 29, 30, 31, 0, ...)としています。[for++] を使い、中央の注目するセルを Array から順番に呼び出しています。そして、まず注目する中央と近傍のセルの状態をビットの並びに変換するのに [expr] を使って計算します。

expr ($s2[($f1+31) % 32] << 2) + ($s2[$f1] << 1) + ($s2[$f1 + 1] % 32)

$s2は起動時に現在の状態を保存してある Array の名前がセットされます。そこから [for++] で 0 から 31 が順番に読み出されるのですが、近傍の表現に注意します。注目する中央のセルが 0 番目のとき 31 を返すように、余りを使っています。31 番目のときも同様です。読み出された値は並それぞれ、シフトします。これで 111 から 000(0 から 7)のどれかになります。そして、この数値をシフトしてやれば規則の想定するビットの並びのどれかになりますので、そのまま AND で演算してやると、合致しているならば 0 以上になります。これより下の処理の流れは [tabwrite] に書き込むための処理です。[expr] のみで書くなら、

expr if ((1 << ($s3[($f1+31) % 32] << 2) + ($s3[$f1] << 1) + ($s3[$f1 + 1] % 32) & $f2) > 0, 1, 0 );
$f1


として 2nd アウトレットをそのまま [tabwrite] の 2nd インレット、同様に 1st どうしをつなげてやります。


CA32.pd
#N canvas 602 53 756 546 10;
#X obj 102 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 119 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 136 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 153 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 170 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 187 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 204 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 221 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 238 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 255 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 272 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 289 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 306 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 323 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 340 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 357 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 374 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 391 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 408 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 425 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 442 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 459 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 476 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 493 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 510 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 1;
#X obj 527 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 544 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 561 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 578 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 595 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 612 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 629 161 tgl 16 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1;
#X obj 190 102 bng 15 250 50 0 empty empty RANDOM 17 7 0 10 -262144 -1 -1;
#X obj 309 102 bng 15 250 50 0 empty empty CLEAR 17 7 0 10 -262144 -1 -1;
#X floatatom 547 101 5 1 255 1 Rule(1-255) - -;
#N canvas 373 312 450 278 (subpatch) 0;
#X array \$0-CURRENT_GENERATION 32 float 2;
#X coords 0 278 1 277 330 70 0;
#X restore 101 378 graph;
#N canvas 0 22 450 278 (subpatch) 0;
#X array \$0-NEXT_GENERATION 32 float 2;
#X coords 0 278 1 277 330 70 0;
#X restore 101 403 graph;
#X obj 547 62 loadbang;
#X msg 547 81 30;
#X obj 428 31 inlet;
#X text 467 30 << Bang next phase;
#X obj 498 498 outlet;
#N canvas 122 43 1313 594 ______________SET_CURRENT_GENERATION_TABLE_______________ 0;
#X obj 16 12 inlet;
#X obj 56 12 inlet;
#X obj 96 12 inlet;
#X obj 136 12 inlet;
#X obj 176 12 inlet;
#X obj 216 12 inlet;
#X obj 256 12 inlet;
#X obj 296 12 inlet;
#X obj 336 12 inlet;
#X obj 376 12 inlet;
#X obj 416 12 inlet;
#X obj 456 12 inlet;
#X obj 496 12 inlet;
#X obj 536 12 inlet;
#X obj 576 12 inlet;
#X obj 616 12 inlet;
#X obj 656 12 inlet;
#X obj 696 12 inlet;
#X obj 736 12 inlet;
#X obj 776 12 inlet;
#X obj 816 12 inlet;
#X obj 856 12 inlet;
#X obj 896 12 inlet;
#X obj 936 12 inlet;
#X obj 976 12 inlet;
#X obj 1016 12 inlet;
#X obj 1056 12 inlet;
#X obj 1096 12 inlet;
#X obj 1136 12 inlet;
#X obj 1176 12 inlet;
#X obj 1216 12 inlet;
#X obj 1256 12 inlet;
#X msg 16 31 \$1 0;
#X msg 56 31 \$1 1;
#X msg 96 31 \$1 2;
#X msg 136 31 \$1 3;
#X msg 176 31 \$1 4;
#X msg 216 31 \$1 5;
#X msg 256 31 \$1 6;
#X msg 296 31 \$1 7;
#X msg 336 31 \$1 8;
#X msg 376 31 \$1 9;
#X msg 416 31 \$1 10;
#X msg 456 31 \$1 11;
#X msg 496 31 \$1 12;
#X msg 536 31 \$1 13;
#X msg 576 31 \$1 14;
#X msg 616 31 \$1 15;
#X msg 656 31 \$1 16;
#X msg 696 31 \$1 17;
#X msg 736 31 \$1 18;
#X msg 776 31 \$1 19;
#X msg 816 31 \$1 20;
#X msg 856 31 \$1 21;
#X msg 896 31 \$1 22;
#X msg 936 31 \$1 23;
#X msg 976 31 \$1 24;
#X msg 1016 31 \$1 25;
#X msg 1056 31 \$1 26;
#X msg 1096 31 \$1 27;
#X msg 1136 31 \$1 28;
#X msg 1176 31 \$1 29;
#X msg 1216 31 \$1 30;
#X msg 1256 31 \$1 31;
#X obj 16 509 tabwrite \$0-CURRENT_GENERATION;
#X connect 0 0 32 0;
#X connect 1 0 33 0;
#X connect 2 0 34 0;
#X connect 3 0 35 0;
#X connect 4 0 36 0;
#X connect 5 0 37 0;
#X connect 6 0 38 0;
#X connect 7 0 39 0;
#X connect 8 0 40 0;
#X connect 9 0 41 0;
#X connect 10 0 42 0;
#X connect 11 0 43 0;
#X connect 12 0 44 0;
#X connect 13 0 45 0;
#X connect 14 0 46 0;
#X connect 15 0 47 0;
#X connect 16 0 48 0;
#X connect 17 0 49 0;
#X connect 18 0 50 0;
#X connect 19 0 51 0;
#X connect 20 0 52 0;
#X connect 21 0 53 0;
#X connect 22 0 54 0;
#X connect 23 0 55 0;
#X connect 24 0 56 0;
#X connect 25 0 57 0;
#X connect 26 0 58 0;
#X connect 27 0 59 0;
#X connect 28 0 60 0;
#X connect 29 0 61 0;
#X connect 30 0 62 0;
#X connect 31 0 63 0;
#X connect 32 0 64 0;
#X connect 33 0 64 0;
#X connect 34 0 64 0;
#X connect 35 0 64 0;
#X connect 36 0 64 0;
#X connect 37 0 64 0;
#X connect 38 0 64 0;
#X connect 39 0 64 0;
#X connect 40 0 64 0;
#X connect 41 0 64 0;
#X connect 42 0 64 0;
#X connect 43 0 64 0;
#X connect 44 0 64 0;
#X connect 45 0 64 0;
#X connect 46 0 64 0;
#X connect 47 0 64 0;
#X connect 48 0 64 0;
#X connect 49 0 64 0;
#X connect 50 0 64 0;
#X connect 51 0 64 0;
#X connect 52 0 64 0;
#X connect 53 0 64 0;
#X connect 54 0 64 0;
#X connect 55 0 64 0;
#X connect 56 0 64 0;
#X connect 57 0 64 0;
#X connect 58 0 64 0;
#X connect 59 0 64 0;
#X connect 60 0 64 0;
#X connect 61 0 64 0;
#X connect 62 0 64 0;
#X connect 63 0 64 0;
#X restore 189 335 pd ______________SET_CURRENT_GENERATION_TABLE_______________ ;
#N canvas 120 339 1600 446 _____________CURRENT_GENERATION_CONTROLLER_______________ 0;
#X obj 16 374 outlet;
#X obj 58 374 outlet;
#X obj 100 374 outlet;
#X obj 142 374 outlet;
#X obj 184 374 outlet;
#X obj 226 374 outlet;
#X obj 268 374 outlet;
#X obj 310 374 outlet;
#X obj 352 374 outlet;
#X obj 394 374 outlet;
#X obj 436 374 outlet;
#X obj 478 374 outlet;
#X obj 520 374 outlet;
#X obj 562 374 outlet;
#X obj 604 374 outlet;
#X obj 646 374 outlet;
#X obj 688 374 outlet;
#X obj 730 374 outlet;
#X obj 772 374 outlet;
#X obj 814 374 outlet;
#X obj 856 374 outlet;
#X obj 898 374 outlet;
#X obj 940 374 outlet;
#X obj 982 374 outlet;
#X obj 1024 374 outlet;
#X obj 1066 374 outlet;
#X obj 1108 374 outlet;
#X obj 1150 374 outlet;
#X obj 1192 374 outlet;
#X obj 1234 374 outlet;
#X obj 1276 374 outlet;
#X obj 1318 374 outlet;
#X obj 344 40 loadbang;
#X obj 544 16 inlet;
#X text 583 14 <- Clear Bang;
#X text 400 39 <- Initializer;
#X msg 544 112 \$1 0;
#X obj 333 20 inlet;
#X text 372 18 <- Random Bang;
#X obj 333 100 until;
#X msg 333 81 32;
#X obj 333 119 random 2;
#X obj 358 157 random 32;
#X obj 333 138 route 0 1;
#X obj 333 195 random 32;
#X msg 333 214 \$1 0;
#X msg 358 176 \$1 1;
#X obj 544 93 for++ 0 31;
#X obj 544 265 route 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31;
#X obj 694 16 inlet;
#X text 733 14 << Bang Next Phase;
#X obj 694 93 for++ 0 31;
#X obj 694 112 tabread \$0-NEXT_GENERATION;
#X obj 694 150 f 0;
#X obj 718 150 + 1;
#X obj 769 169 route 31;
#X msg 769 188 0;
#X obj 694 169 pack;
#X obj 694 131 t b f;
#X obj 344 59 del 8;
#N canvas 1241 43 605 584 NEXT_GENERATION_GENERATOR 0;
#X obj 59 247 inlet;
#X text 97 245 <- Rule (float);
#X obj 44 285 > 0;
#X obj 44 37 inlet;
#X text 82 35 << Start Bang;
#X obj 395 56 float \$0;
#X obj 395 37 loadbang;
#X obj 44 56 for++ 0 31;
#X obj 90 390 + 1;
#X obj 65 390 f 0;
#X obj 198 385 route 31;
#X msg 198 404 0;
#X obj 44 334 t f b;
#X obj 44 467 pack;
#X obj 44 533 tabwrite \$0-NEXT_GENERATION;
#X msg 395 75 symbol \$1-CURRENT_GENERATION;
#X obj 44 266 &;
#X obj 101 75 outlet;
#X text 145 74 << End bang;
#X text 223 531 << Next Generation state;
#X obj 44 209 <<;
#X obj 44 171 t b f;
#X obj 44 190 float 1;
#X text 72 208 << Current Generation state 1 \, 2 \, 4 \, 8 \, 16 \, 32 \, 64 or 128;
#X obj 44 94 expr ($s2[($f1+31) % 32] << 2) + ($s2[$f1] << 1) + ($s2[$f1 + 1] % 32);
#X connect 0 0 16 1;
#X connect 2 0 12 0;
#X connect 3 0 7 0;
#X connect 5 0 15 0;
#X connect 6 0 5 0;
#X connect 7 0 24 0;
#X connect 7 1 17 0;
#X connect 8 0 9 1;
#X connect 9 0 8 0;
#X connect 9 0 10 0;
#X connect 9 0 13 1;
#X connect 10 0 11 0;
#X connect 11 0 9 1;
#X connect 12 0 13 0;
#X connect 12 1 9 0;
#X connect 13 0 14 0;
#X connect 15 0 24 1;
#X connect 16 0 2 0;
#X connect 20 0 16 0;
#X connect 21 0 22 0;
#X connect 21 1 20 1;
#X connect 22 0 20 0;
#X connect 24 0 21 0;
#X restore 694 74 pd NEXT_GENERATION_GENERATOR;
#X obj 859 16 inlet;
#X text 898 14 << Rule (float);
#X obj 1382 374 outlet;
#X text 1284 399 32nd Cell >>;
#X text 17 399 << 1st Cell;
#N canvas 755 322 709 481 __________PUSH_CURRENT_GENERATION__________ 0;
#X obj 14 8 inlet;
#X obj 13 438 outlet;
#X obj 13 419 bang;
#X obj 297 438 outlet;
#X obj 14 28 for++ 0 31;
#X obj 14 48 tabread \$0-CURRENT_GENERATION;
#X obj 14 96 f 0;
#X obj 38 96 + 1;
#X obj 13 334 pack f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f;
#X obj 14 160 pack;
#X obj 14 67 t b f;
#X obj 14 200 route 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31;
#X obj -13 303 float;
#X msg 387 321 0;
#X obj 348 232 t b f b;
#X text 52 7 << Start Bang;
#X text 59 437 << Bang;
#X text 343 436 << Current Generation List;
#X connect 0 0 4 0;
#X connect 2 0 1 0;
#X connect 4 0 5 0;
#X connect 5 0 10 0;
#X connect 6 0 7 0;
#X connect 6 0 9 0;
#X connect 7 0 6 1;
#X connect 8 0 2 0;
#X connect 8 0 3 0;
#X connect 9 0 11 0;
#X connect 10 0 6 0;
#X connect 10 1 9 1;
#X connect 11 0 12 1;
#X connect 11 1 8 1;
#X connect 11 2 8 2;
#X connect 11 3 8 3;
#X connect 11 4 8 4;
#X connect 11 5 8 5;
#X connect 11 6 8 6;
#X connect 11 7 8 7;
#X connect 11 8 8 8;
#X connect 11 9 8 9;
#X connect 11 10 8 10;
#X connect 11 11 8 11;
#X connect 11 12 8 12;
#X connect 11 13 8 13;
#X connect 11 14 8 14;
#X connect 11 15 8 15;
#X connect 11 16 8 16;
#X connect 11 17 8 17;
#X connect 11 18 8 18;
#X connect 11 19 8 19;
#X connect 11 20 8 20;
#X connect 11 21 8 21;
#X connect 11 22 8 22;
#X connect 11 23 8 23;
#X connect 11 24 8 24;
#X connect 11 25 8 25;
#X connect 11 26 8 26;
#X connect 11 27 8 27;
#X connect 11 28 8 28;
#X connect 11 29 8 29;
#X connect 11 30 8 30;
#X connect 11 31 14 0;
#X connect 12 0 8 0;
#X connect 13 0 6 1;
#X connect 14 0 12 0;
#X connect 14 1 8 31;
#X connect 14 2 13 0;
#X restore 694 55 pd __________PUSH_CURRENT_GENERATION__________;
#X text 1426 373 << Current Generation List;
#X connect 32 0 59 0;
#X connect 33 0 47 0;
#X connect 36 0 48 0;
#X connect 37 0 40 0;
#X connect 39 0 41 0;
#X connect 40 0 39 0;
#X connect 41 0 43 0;
#X connect 42 0 46 0;
#X connect 43 0 44 0;
#X connect 43 1 42 0;
#X connect 44 0 45 0;
#X connect 45 0 48 0;
#X connect 46 0 48 0;
#X connect 47 0 36 0;
#X connect 48 0 0 0;
#X connect 48 1 1 0;
#X connect 48 2 2 0;
#X connect 48 3 3 0;
#X connect 48 4 4 0;
#X connect 48 5 5 0;
#X connect 48 6 6 0;
#X connect 48 7 7 0;
#X connect 48 8 8 0;
#X connect 48 9 9 0;
#X connect 48 10 10 0;
#X connect 48 11 11 0;
#X connect 48 12 12 0;
#X connect 48 13 13 0;
#X connect 48 14 14 0;
#X connect 48 15 15 0;
#X connect 48 16 16 0;
#X connect 48 17 17 0;
#X connect 48 18 18 0;
#X connect 48 19 19 0;
#X connect 48 20 20 0;
#X connect 48 21 21 0;
#X connect 48 22 22 0;
#X connect 48 23 23 0;
#X connect 48 24 24 0;
#X connect 48 25 25 0;
#X connect 48 26 26 0;
#X connect 48 27 27 0;
#X connect 48 28 28 0;
#X connect 48 29 29 0;
#X connect 48 30 30 0;
#X connect 48 31 31 0;
#X connect 49 0 66 0;
#X connect 51 0 52 0;
#X connect 52 0 58 0;
#X connect 53 0 54 0;
#X connect 53 0 55 0;
#X connect 53 0 57 0;
#X connect 54 0 53 1;
#X connect 55 0 56 0;
#X connect 56 0 53 1;
#X connect 57 0 48 0;
#X connect 58 0 53 0;
#X connect 58 1 57 1;
#X connect 59 0 40 0;
#X connect 60 0 51 0;
#X connect 61 0 60 1;
#X connect 66 0 60 0;
#X connect 66 1 63 0;
#X restore 190 119 pd _____________CURRENT_GENERATION_CONTROLLER_______________ ;
#X obj 402 73 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1;
#X text 543 498 << Current Generation List;
#X text 142 377 << Current Generation;
#X text 141 402 << Next Generation;
#X obj 609 338 print -Rule_30;
#X connect 0 0 42 0;
#X connect 1 0 42 1;
#X connect 2 0 42 2;
#X connect 3 0 42 3;
#X connect 4 0 42 4;
#X connect 5 0 42 5;
#X connect 6 0 42 6;
#X connect 7 0 42 7;
#X connect 8 0 42 8;
#X connect 9 0 42 9;
#X connect 10 0 42 10;
#X connect 11 0 42 11;
#X connect 12 0 42 12;
#X connect 13 0 42 13;
#X connect 14 0 42 14;
#X connect 15 0 42 15;
#X connect 16 0 42 16;
#X connect 17 0 42 17;
#X connect 18 0 42 18;
#X connect 19 0 42 19;
#X connect 20 0 42 20;
#X connect 21 0 42 21;
#X connect 22 0 42 22;
#X connect 23 0 42 23;
#X connect 24 0 42 24;
#X connect 25 0 42 25;
#X connect 26 0 42 26;
#X connect 27 0 42 27;
#X connect 28 0 42 28;
#X connect 29 0 42 29;
#X connect 30 0 42 30;
#X connect 31 0 42 31;
#X connect 32 0 43 0;
#X connect 33 0 43 1;
#X connect 34 0 43 3;
#X connect 37 0 38 0;
#X connect 38 0 34 0;
#X connect 39 0 43 2;
#X connect 43 0 0 0;
#X connect 43 1 1 0;
#X connect 43 2 2 0;
#X connect 43 3 3 0;
#X connect 43 4 4 0;
#X connect 43 5 5 0;
#X connect 43 6 6 0;
#X connect 43 7 7 0;
#X connect 43 8 8 0;
#X connect 43 9 9 0;
#X connect 43 10 10 0;
#X connect 43 11 11 0;
#X connect 43 12 12 0;
#X connect 43 13 13 0;
#X connect 43 14 14 0;
#X connect 43 15 15 0;
#X connect 43 16 16 0;
#X connect 43 17 17 0;
#X connect 43 18 18 0;
#X connect 43 19 19 0;
#X connect 43 20 20 0;
#X connect 43 21 21 0;
#X connect 43 22 22 0;
#X connect 43 23 23 0;
#X connect 43 24 24 0;
#X connect 43 25 25 0;
#X connect 43 26 26 0;
#X connect 43 27 27 0;
#X connect 43 28 28 0;
#X connect 43 29 29 0;
#X connect 43 30 30 0;
#X connect 43 31 31 0;
#X connect 43 32 41 0;
#X connect 43 32 48 0;
#X connect 44 0 43 2;
#X coords 0 -1 1 1 547 80 2 100 100;

2013年4月13日土曜日

Ethernet

ETHER TYPE IANA "IEEE 802 Numbers"
http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xml

IEEE 802.3 資料
http://standards.ieee.org/about/get/802/802.3.html

2013年3月31日日曜日

公開したくないインスタンス変数を持ちたいけれど、どうしたらよいか?

Objective-Cのはなし。

公開したくないインスタンス変数を持たせたいけれど、どうしたらよいか?
手元に実装コードがなくても既存のクラスにメソッドを追加できるのがカテゴリ。でもインスタンス変数は追加できない。では @property で追加したらどう?ってことで試したけれどだめです。

これにはクラス拡張(class extensions)で対応します。クラス拡張はカテゴリのカテゴリ名を無記名にするだけ。括弧内に名前を与えないので匿名カテゴリ(anonymous categories)と呼ぶこともあるそうです。

@interface ClassName () {
    // インスタンス変数の追加も可能
   id _obj;
}
// 宣言プロパティ
@property NSString *string;
// メソッド
- (void)method;
@end

また、クラス拡張でメソッドを追加した場合はクラス本体のソースコードにメソッドの実装をする必要があります。

2013年1月23日水曜日

Create New Signals!

知っているとは思うが、卿等リリースされたぜ?

Pd-extended 0.43.4

2013年1月9日水曜日

Does Time Waits for Someone?

時間に関するオブジェクトについて
Cocoa は日付と時間を NSDate オブジェクトで表しています。そして NSDate は日付を"点"で(具体的には yyy-mm-dd hh:mm:sss ±TimeZone のかたちで)表しています。そして日付についてあーだこーだするためには、この NSDate と生活時間を表している NSCalendar と構成要素の NSDateComponents を行ったり来たりしてあーだこーだします。詳しくは"Date and Time Programming Guide"を。

2012年12月4日火曜日

How to install bash

bash のインストール
OpenBSD に bash をインストール。まず pkg_add でコンパイル済みのバイナリをインストールします。そのまえに環境変数 PKG_PATHの設定をします。詳しくは pkg_add(1) を。

# PKG_PATH=ftp://お近くの ftp サーバ/`uname -s`/`uname -r`/packages/`uname -p`/
# export PKG_PATH
# pkg_add -i -v bash

ログインシェルとして使用する場合は /etc/shells に書き込む必要がありまが、自動的に/usr/local/bin/bash が /etc/shells に追加されます。

ログインシェルの変更

~$ chsh -s /usr/local/bin/bash

bash のプロンプトを変更
ログインをし直してから

 -bash-4.2# cat .profile > .bash_profile

以下追加
#  Prompt
PS1="\h:\W \u\$ "

編集後に

source .bash_profile

でプロンプトが

ホスト名:dir ユーザ名#or$

になります。

2012年11月26日月曜日

OpenBSD でしょ?

VirtualBox のゲストに OpenBSD をインストールします。 特に理由はありませんが紳士はやっぱり OpenBSD でしょ?ということです。

さて OpenBSD のサイトから"リリースを入手"で、OpenBSD を入手先を探します。 プロトコルは http/ftp のどちらでもよいですが、地域が近いミラーにします。日本ではそれぞれ、ふたつずつあります。

Japan (Ishikawa) http://ftp.jaist.ac.jp/pub/OpenBSD/
Japan (Saitama) http://www.ftp.ne.jp/OpenBSD/

Japan (Ishikawa) ftp://ftp.jaist.ac.jp/pub/OpenBSD/
Japan (Saitama) ftp://ftp.kddilabs.jp/OpenBSD/

現時点(2012年11月25日)の最新版(5.2)を使用することにします。いざ鎌倉というときでもインストールが可能なように OpenBSD 以下のディレクトリから install52.iso をダウンロード。CPUのアーキテクチャは x86_64 の場合 amd64 になります。

適当に設定した仮想マシンに iso イメージをマウントして起動します。インストール項目は基本的にデフォルトにしましたが、以下は変更しています。

キーボード
Choose your keyboard layout ('?' or 'L' for list) [default]
'L' でリストを表示。国名がたくさん出てきますので 'jp' を入力。

タイムサーバ
Start ntpd(8) by default? [no] y
NTP server? (hostname or 'default') [default] <ntpサーバ>
お近くの ntpサーバ をどうぞ。

パッケージの選択
Select sets by entering a set name, a file name pattern or 'all'. De-select
sets by prepending a '-' to the set name, file name pattern or 'all'. Selected
sets are labelled '[X]'.
 [X] bsd             [X] etc52.tgz         [X] xbase52.tgz     [X] xserv52.tgz
 [X] bsd.rd         [X] comp52.tgz       [X] xetc52.tgz
 [X] bsd.mp        [X] man52.tgz        [X] xshare52.tgz
 [X] base52.tgz   [ ] game52.tgz       [X] xfont52.tgz
Set name(s)? (or 'abort' or 'done') [done] -game52.tgz
ゲームは特にいらないかな?

インストールの終了後再起動します。これでインストールは完了です。

2012年5月4日金曜日

SoundCloud

SoundCloud に Pd-extended で生成したシグナルを上げました。
CC で配布していますので、自由にご利用くださいませ。

http://soundcloud.com/generalphotographics

2012年4月17日火曜日

New Signal from Pd

通勤用の音楽を作成します。
丁寧につくっていません。以下ソースです。

main
#N canvas 538 22 356 292 10; #N canvas 523 337 631 325 (subpatch) 0; #X floatatom 4 23 7 0 0 1 METRONORM_0_INTERVAL - -; #X obj 4 4 r METRONORM_0_INTERVAL_INIT_; #X obj 410 -34 loadbang; #X obj 4 230 metro 165; #X obj 4 249 s METRONORM_0_BANG_; #X obj 4 192 s METRONORM_0_INTERVAL_; #X floatatom 25 62 7 0 0 1 METRONORM_1_INTERVAL - -; #X obj 25 43 r METRONORM_0_INTERVAL_INIT_; #X obj 198 193 metro 165; #X obj 198 212 s METRONORM_1_BANG_; #X obj 198 154 s METRONORM_1_INTERVAL_; #X obj 177 81 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X obj 205 58 r RANDOMS_START_INIT_; #X obj 177 103 s RANDOMS_START_; #N canvas 519 177 591 505 VCO 0; #N canvas 144 169 754 583 VCO_0 0; #X obj 61 93 Random; #X obj 560 44 loadbang; #X obj 94 74 r RANDOM_0_INIT_; #X obj 61 131 * 12; #X obj 173 202 + 4; #X obj 173 221 mtof; #X obj 285 221 mtof; #X obj 453 221 mtof; #X obj 258 240 float; #X obj 426 240 float; #X obj 300 107 Random; #X obj 333 88 r RANDOM_1_INIT_; #X obj 483 422 osc~; #X obj 61 221 mtof; #X obj 34 240 float; #X obj 285 202 + 7; #X obj 453 202 + 12; #X obj 483 321 vline~; #X obj 397 221 mtof; #X obj 370 240 float; #X obj 397 202 + 11; #X obj 117 221 mtof; #X obj 90 240 float; #X obj 117 202 + 2; #X obj 483 403 *~; #X obj 498 346 osc~; #X obj 229 221 mtof; #X obj 202 240 float; #X obj 229 202 + 5; #X obj 498 365 +~ 1; #X obj 498 384 /~ 2; #X obj 341 221 mtof; #X obj 314 240 float; #X obj 341 202 + 9; #X obj 483 300 pack f f; #X obj 483 441 lop~ 22050; #X obj 300 126 route 0 1 2 3 4 5 6 7 8 9 10 11; #X obj 528 223 NoiseRandom; #X obj 560 63 delay 100; #X obj 300 68 metro 165; #X obj 146 240 float; #X obj 300 49 inlet; #X obj 483 221 mtof; #X msg 483 202 0; #X obj 61 55 r METRONORM_0_BANG_; #X obj 528 204 r METRONORM_0_BANG_; #X obj 555 243 r METRONORM_0_INTERVAL_; #X obj 528 281 * 165; #X obj 351 49 r METRONORM_0_INTERVAL_; #X msg 560 82 \; RANDOM_0_INIT_ 6 \; RANDOM_1_INIT_ 13 \;; #X obj 483 518 outlet~; #X obj 483 499 *~; #X obj 498 480 r~ RANDOMS_START_SIGNAL_; #X obj 61 112 + 3; #X obj 483 460 *~ 0.3; #X obj 555 262 / 2; #X connect 0 0 53 0; #X connect 1 0 38 0; #X connect 2 0 0 1; #X connect 3 0 4 0; #X connect 3 0 15 0; #X connect 3 0 16 0; #X connect 3 0 20 0; #X connect 3 0 23 0; #X connect 3 0 13 0; #X connect 3 0 28 0; #X connect 3 0 33 0; #X connect 4 0 5 0; #X connect 5 0 40 1; #X connect 6 0 8 1; #X connect 7 0 9 1; #X connect 8 0 34 0; #X connect 9 0 34 0; #X connect 10 0 36 0; #X connect 11 0 10 1; #X connect 12 0 35 0; #X connect 13 0 14 1; #X connect 14 0 34 0; #X connect 15 0 6 0; #X connect 16 0 7 0; #X connect 17 0 24 0; #X connect 17 0 25 0; #X connect 18 0 19 1; #X connect 19 0 34 0; #X connect 20 0 18 0; #X connect 21 0 22 1; #X connect 23 0 21 0; #X connect 24 0 12 0; #X connect 25 0 29 0; #X connect 26 0 27 1; #X connect 27 0 34 0; #X connect 28 0 26 0; #X connect 29 0 30 0; #X connect 30 0 24 1; #X connect 31 0 32 1; #X connect 32 0 34 0; #X connect 33 0 31 0; #X connect 34 0 17 0; #X connect 35 0 54 0; #X connect 36 0 14 0; #X connect 36 1 22 0; #X connect 36 2 40 0; #X connect 36 3 27 0; #X connect 36 4 8 0; #X connect 36 5 32 0; #X connect 36 6 19 0; #X connect 36 7 9 0; #X connect 36 8 14 0; #X connect 36 9 40 0; #X connect 36 10 8 0; #X connect 36 11 9 0; #X connect 36 12 19 0; #X connect 37 0 47 0; #X connect 38 0 49 0; #X connect 39 0 10 0; #X connect 40 0 34 0; #X connect 41 0 39 0; #X connect 42 0 34 0; #X connect 43 0 42 0; #X connect 44 0 0 0; #X connect 45 0 37 0; #X connect 46 0 55 0; #X connect 47 0 34 1; #X connect 48 0 39 1; #X connect 51 0 50 0; #X connect 52 0 51 1; #X connect 53 0 3 0; #X connect 54 0 51 0; #X connect 55 0 47 1; #X restore -11 47 pd VCO_0; #N canvas 555 121 736 604 VCO_1 0; #X obj 61 93 Random; #X obj 560 44 loadbang; #X obj 61 131 * 12; #X obj 61 112 + 3; #X obj 173 212 + 4; #X obj 173 231 mtof; #X obj 285 231 mtof; #X obj 453 231 mtof; #X obj 258 250 float; #X obj 426 250 float; #X obj 300 107 Random; #X obj 483 432 osc~; #X obj 61 231 mtof; #X obj 34 250 float; #X obj 285 212 + 7; #X obj 453 212 + 12; #X obj 483 331 vline~; #X obj 397 231 mtof; #X obj 370 250 float; #X obj 397 212 + 11; #X obj 117 231 mtof; #X obj 90 250 float; #X obj 117 212 + 2; #X obj 483 413 *~; #X obj 498 356 osc~; #X obj 229 231 mtof; #X obj 202 250 float; #X obj 229 212 + 5; #X obj 498 375 +~ 1; #X obj 498 394 /~ 2; #X obj 341 231 mtof; #X obj 314 250 float; #X obj 341 212 + 9; #X obj 483 451 lop~ 22050; #X obj 300 126 route 0 1 2 3 4 5 6 7 8 9 10 11; #X obj 528 233 NoiseRandom; #X obj 560 63 delay 100; #X obj 300 68 metro 165; #X obj 146 250 float; #X obj 300 49 inlet; #X obj 483 231 mtof; #X msg 483 212 0; #X obj 528 291 * 165; #X msg 560 82 \; RANDOM_2_INIT_ 6 \; RANDOM_3_INIT_ 13 \;; #X obj 333 88 r RANDOM_3_INIT_; #X obj 94 74 r RANDOM_2_INIT_; #X obj 61 55 r METRONORM_1_BANG_; #X obj 351 49 r METRONORM_1_INTERVAL_; #X obj 528 214 r METRONORM_1_BANG_; #X obj 555 253 r METRONORM_1_INTERVAL_; #X obj 483 527 outlet~; #X obj 483 508 *~; #X obj 498 489 r~ RANDOMS_START_SIGNAL_; #X obj 483 310 pack f f; #X obj 483 470 *~ 0.3; #X obj 555 272 / 2; #X connect 0 0 3 0; #X connect 1 0 36 0; #X connect 2 0 4 0; #X connect 2 0 14 0; #X connect 2 0 15 0; #X connect 2 0 19 0; #X connect 2 0 22 0; #X connect 2 0 12 0; #X connect 2 0 27 0; #X connect 2 0 32 0; #X connect 3 0 2 0; #X connect 4 0 5 0; #X connect 5 0 38 1; #X connect 6 0 8 1; #X connect 7 0 9 1; #X connect 8 0 53 0; #X connect 9 0 53 0; #X connect 10 0 34 0; #X connect 11 0 33 0; #X connect 12 0 13 1; #X connect 13 0 53 0; #X connect 14 0 6 0; #X connect 15 0 7 0; #X connect 16 0 23 0; #X connect 16 0 24 0; #X connect 17 0 18 1; #X connect 18 0 53 0; #X connect 19 0 17 0; #X connect 20 0 21 1; #X connect 22 0 20 0; #X connect 23 0 11 0; #X connect 24 0 28 0; #X connect 25 0 26 1; #X connect 26 0 53 0; #X connect 27 0 25 0; #X connect 28 0 29 0; #X connect 29 0 23 1; #X connect 30 0 31 1; #X connect 31 0 53 0; #X connect 32 0 30 0; #X connect 33 0 54 0; #X connect 34 0 13 0; #X connect 34 1 21 0; #X connect 34 2 38 0; #X connect 34 3 26 0; #X connect 34 4 8 0; #X connect 34 5 31 0; #X connect 34 6 18 0; #X connect 34 7 9 0; #X connect 34 8 13 0; #X connect 34 9 38 0; #X connect 34 10 8 0; #X connect 34 11 9 0; #X connect 34 12 18 0; #X connect 35 0 42 0; #X connect 36 0 43 0; #X connect 37 0 10 0; #X connect 38 0 53 0; #X connect 39 0 37 0; #X connect 40 0 53 0; #X connect 41 0 40 0; #X connect 42 0 53 1; #X connect 44 0 10 1; #X connect 45 0 0 1; #X connect 46 0 0 0; #X connect 47 0 37 1; #X connect 48 0 35 0; #X connect 49 0 55 0; #X connect 51 0 50 0; #X connect 52 0 51 1; #X connect 53 0 16 0; #X connect 54 0 51 0; #X connect 55 0 42 1; #X restore 147 47 pd VCO_1; #X obj 49 5 r RANDOMS_START_; #N canvas 274 243 256 338 VOC_2 0; #X obj -98 9 inlet~; #X obj -98 267 outlet~; #X obj -98 48 *~; #X obj -83 29 r~ RANDOMS_START_SIGNAL_; #N canvas 142 349 486 411 VOICE-FM 0; #X obj 92 79 mtof; #X obj 62 304 osc~; #X obj 92 164 osc~; #X obj 92 38 inlet~; #X obj 62 344 outlet~; #X obj 372 19 loadbang; #X msg 370 69 0; #X msg 402 69 0.25; #X obj 92 183 +~ 1; #X obj 92 202 /~ 2; #X obj 92 139 vline~; #X obj 62 283 *~; #X obj 62 325 *~; #X obj 193 301 osc~; #X obj 193 340 outlet~; #X obj 193 321 *~; #X obj 92 59 fiddle~ 8192 1 20 0; #X obj 203 163 vline~; #X obj 32 183 phasor~; #X obj 77 222 +~; #X obj 203 102 dbtorms; #X obj 203 123 clip 0 1; #X msg 203 143 \$1 5; #X msg 92 119 \$1 5; #X obj 92 99 * 3; #X connect 0 0 24 0; #X connect 1 0 12 0; #X connect 2 0 8 0; #X connect 3 0 16 0; #X connect 5 0 6 0; #X connect 5 0 7 0; #X connect 6 0 2 1; #X connect 6 0 1 1; #X connect 7 0 13 1; #X connect 8 0 9 0; #X connect 9 0 19 1; #X connect 10 0 11 0; #X connect 10 0 2 0; #X connect 10 0 18 0; #X connect 11 0 1 0; #X connect 11 0 13 0; #X connect 12 0 4 0; #X connect 13 0 15 0; #X connect 15 0 14 0; #X connect 16 0 0 0; #X connect 16 3 20 0; #X connect 17 0 15 1; #X connect 17 0 12 1; #X connect 18 0 19 0; #X connect 19 0 11 1; #X connect 20 0 21 0; #X connect 21 0 22 0; #X connect 22 0 17 0; #X connect 23 0 10 0; #X connect 24 0 23 0; #X restore -98 68 pd VOICE-FM; #X obj 31 273 outlet~; #X obj -98 95 *~ 0.5; #X obj 31 102 *~ 0.5; #X obj -83 153 vline~; #X obj -98 172 *~; #X obj -83 134 pack f 10; #X obj -98 248 *~; #X obj -98 191 hip~ 10; #X obj -98 210 lop~ 22050; #X obj -83 229 r~ VCO_0_SIGNAL_; #X obj 46 235 r~ VCO_1_SIGNAL_; #X obj 46 159 vline~; #X obj 31 178 *~; #X obj 46 140 pack f 10; #X obj 31 216 lop~ 22050; #X obj 31 197 hip~ 10; #X obj 31 254 *~; #X obj -83 114 r PAN_0_R_; #X obj 46 121 r PAN_0_L_; #X connect 0 0 2 0; #X connect 2 0 4 0; #X connect 3 0 2 1; #X connect 4 0 6 0; #X connect 4 1 7 0; #X connect 6 0 9 0; #X connect 7 0 17 0; #X connect 8 0 9 1; #X connect 9 0 12 0; #X connect 10 0 8 0; #X connect 11 0 1 0; #X connect 12 0 13 0; #X connect 13 0 11 0; #X connect 14 0 11 1; #X connect 15 0 21 1; #X connect 16 0 17 1; #X connect 17 0 20 0; #X connect 18 0 16 0; #X connect 19 0 21 0; #X connect 20 0 19 0; #X connect 21 0 5 0; #X connect 22 0 10 0; #X connect 23 0 18 0; #X restore -4 205 pd VOC_2; #N canvas 961 404 306 320 PAN_0 0; #X obj 107 99 NoiseRandom; #X obj 107 79 r METRONORM_0_BANG_; #X obj 122 126 pi; #X obj 107 164 *; #X obj 107 197 cos; #X obj 122 145 / 2; #X obj 131 197 sin; #X obj 107 237 outlet; #X obj 131 216 outlet; #X connect 0 0 3 0; #X connect 1 0 0 0; #X connect 2 0 5 0; #X connect 3 0 4 0; #X connect 3 0 6 0; #X connect 4 0 7 0; #X connect 5 0 3 1; #X connect 6 0 8 0; #X restore 362 25 pd PAN_0; #X obj 143 454 s~ AUDIO_SIGNAL_R_; #X obj -26 454 s~ AUDIO_SIGNAL_L_; #N canvas 107 326 701 531 VOC_3 0; #X obj 377 33 table RHYTHM; #X obj 21 27 r METRONORM_0_BANG_; #X obj 377 52 table RHYTHM_ENVELOPE; #X obj 378 92 loadbang; #X obj 35 51 noise~; #X obj 35 70 tabwrite~ RHYTHM; #X obj 184 266 tabread4~ RHYTHM; #X obj 177 286 tabread4~ RHYTHM_ENVELOPE; #X obj 177 305 *~; #X msg 378 112 \; RHYTHM_ENVELOPE resize 1025 \; RHYTHM resize 1025 \;; #X obj 177 247 vline~; #X obj -98 79 inlet~; #X obj -91 275 tabread4~ RHYTHM; #X obj -98 295 tabread4~ RHYTHM_ENVELOPE; #X obj -98 256 vline~; #X obj 63 353 *~; #X obj 240 171 r METRONORM_0_INTERVAL_; #X obj 177 209 pack 1024 f; #X msg 177 228 0 \, \$1 \$2; #X obj -35 199 Random; #X obj -98 218 pack 1024 f; #X msg -98 237 0 \, \$1 \$2; #X obj -2 180 r METRONORM_0_INTERVAL_; #X obj 63 426 outlet~; #N canvas 0 22 249 360 RHYTHM_ENVELOPE_INIT 0; #X obj 30 21 loadbang; #X msg 30 59 start; #X obj 30 302 tabwrite RHYTHM_ENVELOPE; #X obj 45 147 pi; #X obj 30 166 *; #X obj 30 40 delay 20; #X obj 30 244 t f b; #X obj 171 283 float 0; #X obj 30 185 cos; #X obj 30 128 / 1024; #X obj 30 204 + 1; #X obj 30 224 / 2; #X obj 30 80 for++ 0 1024; #X connect 0 0 5 0; #X connect 1 0 12 0; #X connect 3 0 4 1; #X connect 4 0 8 0; #X connect 5 0 1 0; #X connect 6 0 2 0; #X connect 6 1 7 0; #X connect 7 0 2 1; #X connect 8 0 10 0; #X connect 9 0 4 0; #X connect 10 0 11 0; #X connect 11 0 6 0; #X connect 12 0 7 1; #X connect 12 0 9 0; #X restore 377 72 pd RHYTHM_ENVELOPE_INIT; #X obj -98 314 *~; #X obj 63 388 *~; #X obj 78 369 r~ RANDOMS_START_SIGNAL_; #X obj 240 190 * 0.75; #X obj -98 99 threshold~ 0.595 0 -0.2 0; #X obj 63 407 *~ 0.2; #X connect 1 0 5 0; #X connect 3 0 9 0; #X connect 4 0 5 0; #X connect 6 0 8 1; #X connect 7 0 8 0; #X connect 8 0 15 1; #X connect 10 0 6 0; #X connect 10 0 7 0; #X connect 11 0 29 0; #X connect 12 0 25 1; #X connect 13 0 25 0; #X connect 14 0 12 0; #X connect 14 0 13 0; #X connect 15 0 26 0; #X connect 16 0 28 0; #X connect 17 0 18 0; #X connect 18 0 10 0; #X connect 19 0 20 1; #X connect 20 0 21 0; #X connect 21 0 14 0; #X connect 22 0 19 1; #X connect 25 0 15 0; #X connect 26 0 30 0; #X connect 27 0 26 1; #X connect 28 0 17 1; #X connect 29 0 17 0; #X connect 29 0 20 0; #X connect 29 0 19 0; #X connect 29 1 17 0; #X connect 29 1 20 0; #X connect 30 0 23 0; #X restore 311 217 pd VOC_3; #X obj -11 85 s~ VCO_0_SIGNAL_; #X obj 147 85 s~ VCO_1_SIGNAL_; #X obj 311 236 s~ VCO_3_SIGNAL_; #X obj 311 179 r~ VCO_0_SIGNAL_; #X obj 317 198 r~ VCO_1_SIGNAL_; #X obj 161 430 r~ VCO_3_SIGNAL_; #X obj -6 66 delwrite~ VCO_0_DL_ 100; #X obj 143 374 delread~ VCO_0_DL_ 35; #X obj 154 66 delwrite~ VCO_1_DL_ 100; #X obj -19 393 delread~ VCO_1_DL_ 35; #X obj 362 63 s PAN_0_L_; #X obj 407 44 s PAN_0_R_; #X obj 41 224 s~ VCO_2_R_SIGNAL_; #X obj -4 243 s~ VCO_2_L_SIGNAL_; #X obj 154 412 r~ VCO_2_R_SIGNAL_; #X obj -4 167 r~ VCO_0_SIGNAL_; #X obj 13 186 r~ VCO_1_SIGNAL_; #X obj -26 374 r~ VCO_0_SIGNAL_; #X obj 149 393 r~ VCO_1_SIGNAL_; #X obj -12 412 r~ VCO_2_L_SIGNAL_; #X obj -7 432 r~ VCO_3_SIGNAL_; #X connect 0 0 8 0; #X connect 0 0 14 0; #X connect 1 0 9 0; #X connect 1 0 16 0; #X connect 2 0 0 0; #X connect 2 0 1 0; #X connect 3 0 21 0; #X connect 3 1 20 0; #X connect 4 0 18 0; #X connect 4 1 19 0; #X connect 7 0 10 0; #X connect 11 0 7 0; #X connect 12 0 7 0; #X connect 13 0 5 0; #X connect 15 0 5 0; #X connect 17 0 6 0; #X connect 22 0 5 0; #X connect 23 0 3 0; #X connect 24 0 3 0; #X connect 25 0 6 0; #X connect 26 0 5 0; #X connect 27 0 6 0; #X connect 28 0 6 0; #X restore 410 175 pd VCO; #X obj 410 36 r RANDOMS_START_; #X obj 410 74 vline~; #X obj 410 93 s~ RANDOMS_START_SIGNAL_; #X msg 410 55 \$1 20; #X msg 410 -13 \; RANDOMS_START_INIT_ 0 \; METRONORM_0_INTERVAL_INIT_ 165 \;; #X obj 198 173 r RANDOMS_START_; #X obj 4 211 r RANDOMS_START_; #N canvas 0 22 233 200 DAC 0; #X obj 56 89 DAC~; #X obj 77 64 r~ AUDIO_SIGNAL_R_; #X obj 56 41 r~ AUDIO_SIGNAL_L_; #X connect 1 0 0 1; #X connect 2 0 0 0; #X restore 410 195 pd DAC; #N canvas 917 22 202 295 REC 1; #X obj 29 -1 r~ AUDIO_SIGNAL_R_; #X obj 21 -24 r~ AUDIO_SIGNAL_L_; #X floatatom 37 22 5 0 0 0 - - -; #X floatatom 45 49 5 0 0 0 - - -; #X floatatom 53 72 5 0 0 0 - - -; #X obj 14 94 Record~; #X floatatom 14 120 5 0 0 0 - - -; #X obj 14 -48 r REC_; #X connect 0 0 5 2; #X connect 1 0 5 1; #X connect 2 0 5 3; #X connect 3 0 5 4; #X connect 4 0 5 5; #X connect 5 0 6 0; #X connect 7 0 5 0; #X restore 410 215 pd REC; #X obj 88 127 tgl 15 0 empty empty REC 17 7 0 10 -262144 -1 -1 0 1 ; #X obj 88 155 s REC_; #X connect 0 0 3 1; #X connect 0 0 5 0; #X connect 1 0 0 0; #X connect 2 0 19 0; #X connect 3 0 4 0; #X connect 6 0 8 1; #X connect 6 0 10 0; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 11 0 13 0; #X connect 12 0 11 0; #X connect 15 0 18 0; #X connect 16 0 17 0; #X connect 18 0 16 0; #X connect 20 0 8 0; #X connect 21 0 3 0; #X connect 24 0 25 0; #X coords 0 1 100 -1 200 150 1 0 0; #X restore 33 117 graph; #X msg 33 32 \; pd dsp \$1; #X obj 33 14 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 ; #X connect 2 0 1 0;

[DAC~]
#N canvas 785 146 450 300 10; #X obj 206 170 dac~; #X obj 227 149 clip~ -1 1; #X obj 206 98 clip~ -1 1; #X obj 206 77 inlet~; #X obj 227 129 inlet~; #X connect 1 0 0 1; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 1 0;

[Random]
#N canvas 694 402 327 192 10; #X obj 62 -8 inlet; #X obj 145 46 inlet; #X msg 90 34 seed \$1; #N canvas 519 166 252 194 SEED_GENERATOR 1; #X obj 11 11 loadbang; #X floatatom 11 65 5 0 0 0 - - -; #X floatatom 45 65 5 0 0 0 - - -; #X floatatom 79 65 5 0 0 0 - - -; #X floatatom 113 65 10 0 0 0 - - -; #X obj 11 30 time GTM; #X obj 98 127 +; #X obj 64 128 +; #X obj 30 128 +; #X obj 83 151 +; #X obj 49 152 +; #X obj 68 174 +; #X obj 68 195 outlet; #X obj 113 92 * 1000; #X connect 0 0 5 0; #X connect 1 0 8 0; #X connect 2 0 7 0; #X connect 2 0 8 1; #X connect 3 0 6 0; #X connect 3 0 7 1; #X connect 4 0 13 0; #X connect 5 0 1 0; #X connect 5 1 2 0; #X connect 5 2 3 0; #X connect 5 3 4 0; #X connect 6 0 9 1; #X connect 7 0 9 0; #X connect 7 0 10 1; #X connect 8 0 10 0; #X connect 9 0 11 1; #X connect 10 0 11 0; #X connect 11 0 12 0; #X connect 13 0 6 1; #X restore 90 14 pd SEED_GENERATOR; #X obj 62 147 outlet; #X obj 62 128 random 10; #X connect 0 0 5 0; #X connect 1 0 5 1; #X connect 2 0 5 0; #X connect 3 0 2 0; #X connect 5 0 4 0; #X coords 0 0 1 1 100 17 0;

[Record~]
#N canvas 205 272 635 470 10; #X obj 64 31 tgl 15 0 empty empty REC 17 7 0 10 -262144 -1 -1 0 1; #X obj 64 50 route 1 0; #X obj 160 229 vline~; #X obj 76 323 *~; #X obj 160 269 *~; #X obj 64 70 savepanel; #X obj 64 363 writesf~ 2; #X obj 84 117 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X msg 85 142 start; #X obj 160 174 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 76 303 inlet~; #X obj 175 250 inlet~; #X obj 86 248 print REC; #X msg 134 141 stop; #N canvas 485 123 450 300 RECORDING_TIMER 0; #X obj 123 29 inlet; #X obj 203 29 inlet; #X obj 271 29 inlet; #X obj 232 138 float 0; #X obj 84 138 float 0; #X obj 168 85 t b b b; #X obj 201 186 +; #X obj 179 221 +; #X obj 183 -17 loadbang; #X obj 179 241 outlet; #X obj 271 48 * 1; #X obj 203 48 * 60; #X obj 123 48 * 3600; #X obj 164 138 float 300; #X obj 82 114 delay 30; #X obj 164 113 delay 30; #X obj 232 112 delay 30; #X connect 0 0 12 0; #X connect 1 0 11 0; #X connect 2 0 10 0; #X connect 3 0 6 1; #X connect 4 0 7 0; #X connect 5 0 14 0; #X connect 5 1 15 0; #X connect 5 2 16 0; #X connect 6 0 7 1; #X connect 7 0 9 0; #X connect 8 0 5 0; #X connect 10 0 3 1; #X connect 10 0 5 0; #X connect 11 0 5 0; #X connect 11 0 13 1; #X connect 12 0 4 1; #X connect 12 0 5 0; #X connect 13 0 6 0; #X connect 14 0 4 0; #X connect 15 0 13 0; #X connect 16 0 3 0; #X restore 427 168 pd RECORDING_TIMER; #X obj 427 149 inlet; #X obj 479 149 inlet; #X obj 532 149 inlet; #X obj 160 191 delay 25; #X obj 420 212 - 1; #X msg 348 171 bang; #X obj 348 212 int 300000; #X obj 348 191 metro 1000; #X obj 348 262 route 1; #X obj 399 242 == 0; #X obj 399 263 route 1; #X text 354 20 inlet~ 1: Audio signal 1; #X text 354 39 inlet~ 2: Audio signal 2; #X obj 64 11 inlet; #X obj 470 244 outlet; #X obj 348 241 == 10; #X msg 235 211 0 9950; #X msg 160 210 0 \, 1 25; #X text 354 1 inlet 0: Start \, Stop; #X text 354 58 inlet 3: Hour; #X text 354 77 inlet 4: Minute; #X text 354 96 inlet 5: Second; #X msg 64 90 open -bytes 4 -wave \$1.wav; #X connect 0 0 1 0; #X connect 1 0 5 0; #X connect 1 1 13 0; #X connect 2 0 3 1; #X connect 2 0 4 0; #X connect 3 0 6 0; #X connect 4 0 6 1; #X connect 5 0 37 0; #X connect 7 0 8 0; #X connect 7 0 20 0; #X connect 8 0 9 0; #X connect 8 0 6 0; #X connect 8 0 12 0; #X connect 9 0 18 0; #X connect 10 0 3 0; #X connect 11 0 4 1; #X connect 13 0 12 0; #X connect 13 0 6 0; #X connect 13 0 22 0; #X connect 14 0 21 1; #X connect 15 0 14 0; #X connect 16 0 14 1; #X connect 17 0 14 2; #X connect 18 0 32 0; #X connect 19 0 21 1; #X connect 20 0 22 0; #X connect 21 0 19 0; #X connect 21 0 24 0; #X connect 21 0 29 0; #X connect 21 0 30 0; #X connect 22 0 21 0; #X connect 23 0 31 0; #X connect 24 0 25 0; #X connect 25 0 13 0; #X connect 28 0 0 0; #X connect 30 0 23 0; #X connect 31 0 2 0; #X connect 32 0 2 0; #X connect 37 0 6 0; #X connect 37 0 7 0;

2012年2月19日日曜日

To increase output for a kitten.

I/O Kit とは?
以前ネットワークをキャプチャするコマンドラインツールを作成しましたが、ioctl を使ってネットワークインターフェイス名を取得していました。探索を I/O Kit の流儀でおこなえるようにします。その前にごくごく簡単に I/O Kit について。

I/O Kit は 以前の Mac OS 9 や流れをくむ FreeBSD のドライバモデルの機能が不十分なので、Mac OS X のために Apple が開発したものです。そして、

The I/O Kit is a collection of system frameworks, libraries, tools, and other resources for creating device drivers in Mac OS X. It is based on an object-oriented programming model implemented in a restricted form of C++ that omits features unsuitable for use within a multithreaded kernel. By modeling the hardware connected to a Mac OS X system and abstracting common functionality for devices in particular categories, the I/O Kit streamlines the process of device-driver development.

I/O Kit は Mac OS X でデバイスドライバを作成するためのシステムフレームワーク、ライブラリ、ツール、その他リソースの集まりです。マルチスレッドのカーネルでの使用に適さない機能を省略した、制限された形式の C++ で実装されているオブジェクト指向プログラミングモデルに基づいています。I/O Kit は Mac OS X システムに接続されているハードウェアをモデル化することによって、特定のカテゴリのなかでデバイスに共通の機能を抽象化し、デバイスドライバ開発過程を効率化します。

なるほど。さらに、

I/O Kit A kernel-resident, object-oriented environment in Darwin that provides a model of system hardware. Each type of service or device is represented by one or more C++ classes in a family; each available service or device is represented by an instance (object) of that class.

I/O Kit とは、カーネルに常駐していて、システムハードウェアのモデルを提供する Darwin 中にあるオブジェクト指向の環境です。サービスやデバイスの各タイプはファミリのひとつ以上の C++ のクラスで表現されています。それぞれ利用可能なサービスやデバイスはそのクラスのインスタンス(オブジェクト)によって表現されています。


つまり?
I/O Kit とは
  1. I/O Kit とはデバイスドライバを開発するためのフレームワークのこと。目的の機能を持つデバイスドライバがない場合、デバイスドライバを開発することになります。限定された C++ を使って目的の機能を実現するデバイスドライバを作成します。
  2. I/O Kit とはカーネルに常駐するシステムハードウェアモデルを提供する、オブジェクトのこと。Mac OS X に接続されているハードウェアのデバイスやドライバの情報を管理しています。デバイスやドライバを利用する場合は I/O Kit から目的のデバイスやドライバを絞り込み、I/O Kit が提供する目的のインターフェイスを使用します。
です。


ioctl を使ってネットワークインターフェイス名を取得する
+ (NSArray *)interfaces
{
    int socketFD,length, lastLength;
    char *buffer;
    struct ifconf ifc;
    
    socketFD = socket(AF_INET, SOCK_DGRAM, 0);
    lastLength = 0;
    length = sizeof(struct ifreq) * 100;        // 初期値
    
    /*//////////////////////////////////////////////////////////////////////////
     ioctl を使って ネットワークインターフェイスの情報を問い合わせる。
     この方法は SIOCGIFCONF が適切な情報を全て必ず返しているかは
     バッファに収まるかどうかによるので、
     ifc構造体の長さが前回に取得した長さと一致した場合に
     全ての情報を適切に取得できたと看做している。
    /////////////////////////////////////////////////////////////////////////*/
    for (; ;) {
        
        buffer = (char *)calloc(length, sizeof(char));
        ifc.ifc_len = length;
        ifc.ifc_ifcu.ifcu_buf = buffer;
        
        if ( ioctl(socketFD, SIOCGIFCONF, &ifc) < 0) {
            
            free(buffer);
            return nil;
            
        } 
        else {
            
            if (ifc.ifc_len == lastLength) {
                break;
            }
            
            lastLength = ifc.ifc_len;
        }
        
        length += sizeof(struct ifreq) * 10;
        free(buffer);
    }
    
    close(socketFD);
    
    struct ifreq *ifr = (struct ifreq *)buffer;
    int next = 0;
    NSMutableArray *interfaces = [NSMutableArray array];
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    while (ifr < (struct ifreq *)(buffer + lastLength)) {
        
        
        ifr = (struct ifreq *)(buffer + next);
        
        NSString *name = [NSString stringWithCString:ifr->ifr_name
                                            encoding:NSUTF8StringEncoding];
        
        if ([name isEqualToString:@""] == NO) {
            
            // 同じ名前のインターフェイスはいらない。
            [interfaces removeObject:name];
            [interfaces addObject:name];
            
        }
        
        next += IFNAMSIZ + ifr->ifr_ifru.ifru_addr.sa_len;
        
    }
    
    free(buffer);
    [pool drain];
    
    return (NSArray *)interfaces;
    
}

I/O Kit を使ってネットワークインターフェイス名を取得する
+ (NSArray *)interfaces
{

    IOReturn ioReturnCode;
    mach_port_t masterPort;
    
    CFMutableDictionaryRef matchingDictionary;
    
    io_iterator_t iterator;
    io_object_t object;
    
    NSMutableArray *interfaces = [NSMutableArray array];
    
    // マスターポートの取得
    ioReturnCode = IOMasterPort(MACH_PORT_NULL, &masterPort);
    
    if (ioReturnCode != KERN_SUCCESS) {
        NSLog(@"IOMasterPort did not return KERN_SUCCESS");
        return nil;
    }
    
    // ディクショナリの作成
    matchingDictionary = IOServiceMatching(kIOEthernetInterfaceClass);
    
    if (matchingDictionary == NULL) {
        NSLog(@"IOServiceMatching returned a NULL Dictionary.");
        return nil;
    }

    // I/O Registry の中から辞書に一致するものを検索する
    ioReturnCode = KERN_SUCCESS;
    ioReturnCode = IOServiceGetMatchingServices(masterPort,
                                                matchingDictionary,
                                                &iterator);

    if (ioReturnCode != KERN_SUCCESS) {
        NSLog(@"IOServiceGetMatchingServicesdid did not return KERN_SUCCESS.");
        return nil;
    }

    while (object = IOIteratorNext(iterator)) {
        
        CFStringRef deviceName = NULL;
        
        // 一致したオブジェクトから BSD 名を取得する。
        deviceName = IORegistryEntryCreateCFProperty(object,
                                                     CFSTR(kIOBSDNameKey),
                                                     kCFAllocatorDefault,
                                                     0);
        
        if (deviceName) 
            [interfaces addObject:(NSString *)deviceName];
            CFRelease(deviceName);
        }
        
        IOObjectRelease(object);
    }

    return (NSArray *)interfaces;
}

ioctl のではバッファに収まったかどうかで取得できたと看做しているのが少し気持ち悪い感がありましたが、I/O Kit は的確に答えを出してくれています。BPF のフィルタマシンに渡すプログラムのコンパイルを libpcap に肩代わりさせていましたが、こうゆうことまで I/O Kit を通して出来るのでしょうか?

2012年1月31日火曜日

She said, It is nasty to wire!

MBP を通して iPhone をインターネットに接続する。
iPhone の Wi-Fi 設定が DHCP ではネットワークに接続できませんでした。
Mac のログを見てみると、

xx/xx/xx 1:24:44    Firewall[58]    Deny InternetSharing data in from ...

インターネットの共有データが拒否されています。
OSX Server でないので DHCP サーバがないから?
仕方なく DHCP ではなく「静的」を選んで設定します。

IPアドレス iPhone に割当てるアドレス。AirMac インターフェイスと同じネットワークにする。
サブネットマスク AirMac のIPアドレスに応じて適当に。
ルータ AirMac インターフェイスのアドレス。
DNS Mac が使っている DNS のアドレス。nslookup を使って調べるのがよろし。
検索ドメイン あれば。空白のままでもよい。

無事接続されました。

2011年12月5日月曜日

Speak FFT a Little in PD

Pure Data で FFT について。
貼付けたら結構長くなりましが、以下ソースです。

#N canvas 89 22 910 751 10; #X obj 0 -1 cnv 15 300 600 empty empty empty 20 12 0 14 -233017 -66577 0; #X obj 303 -1 cnv 15 300 600 empty empty empty 20 12 0 14 -233017 -66577 0; #X obj 606 -1 cnv 15 300 600 empty empty empty 20 12 0 14 -233017 -66577 0; #X obj 606 602 cnv 15 300 120 empty empty Modules 20 12 0 14 -228856 -191407 0; #X obj 1 602 cnv 15 602 120 empty empty Controller 20 12 0 14 -228856 -191407 0; #N canvas 968 286 450 300 INITIALIZE 0; #X obj 12 7 loadbang; #X obj 83 8 bng 15 250 50 0 empty SET_DEFAULTS_MESSAGE_ SET_DEFAULTS 17 7 0 10 -262144 -1 -1; #N canvas 80 135 450 300 DSP_BLOCK_SIZE 0; #X obj 12 22 inlet; #X msg 12 64 \; DSP_BLOCK_SIZE_INITIALIZE_MESSAGE_ \$1; #X msg 12 43 6; #X connect 0 0 2 0; #X connect 2 0 1 0; #X restore 12 187 pd DSP_BLOCK_SIZE; #N canvas 594 164 450 300 TABLES 0; #X obj 8 11 inlet; #N canvas 801 469 454 350 WAVE 0; #X obj 7 5 inlet; #X msg 7 35 256 512; #X msg 7 62 \; WAVE_1_FREQUENCY_INITIALIZE_MESSAGE_ \$1 \; WAVE_2_FREQUENCY_INITIALIZE_MESSAGE_ \$2 \;; #X obj 11 127 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X obj 11 181 pack f f; #X msg 11 215 \; Wave resize \$1 \; Wave_1 resize \$1 \; Wave_2 resize \$1 \; Wave bounds 0 1 \$2 -1 \; Wave_1 bounds 0 1 \$2 -1 \; Wave_2 bounds 0 1 \$2 -1 \;; #X obj 11 145 expr $f1 \; $f1 - 1 \;; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 3 0 6 0; #X connect 4 0 5 0; #X connect 6 0 4 0; #X connect 6 1 4 1; #X restore 8 50 pd WAVE; #N canvas 340 371 450 300 AMPLITUDE 0; #X obj 16 28 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X obj 16 82 pack f f; #X obj 16 46 expr $f1 \; $f1 - 1 \;; #X msg 16 107 \; Amplitude resize \$1 \; Amplitude bounds 0 1 \$2 0 \;; #X connect 0 0 2 0; #X connect 1 0 3 0; #X connect 2 0 1 0; #X connect 2 1 1 1; #X restore 8 69 pd AMPLITUDE; #N canvas 340 371 450 300 Phase 0; #X obj 16 28 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X obj 16 82 pack f f; #X obj 16 46 expr $f1 \; $f1 - 1 \;; #X msg 16 107 \; Phase resize \$1 \; Phase bounds 0 3.14159 \$2 -3.14159 \;; #X connect 0 0 2 0; #X connect 1 0 3 0; #X connect 2 0 1 0; #X connect 2 1 1 1; #X restore 8 88 pd Phase; #N canvas 107 61 450 300 WINDOW 0; #X obj 26 38 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X obj 26 92 pack f f; #X obj 26 56 expr $f1 \; $f1 - 1 \;; #X msg 26 117 \; Window resize \$1 \; Window bounds 0 1 \$2 0 \;; #X connect 0 0 2 0; #X connect 1 0 3 0; #X connect 2 0 1 0; #X connect 2 1 1 1; #X restore 8 109 pd WINDOW; #X connect 0 0 1 0; #X restore 35 164 pd TABLES; #X connect 0 0 2 0; #X connect 0 0 3 0; #X connect 1 0 2 0; #X connect 1 0 3 0; #X restore 625 632 pd INITIALIZE; #X obj 102 634 tgl 15 0 DSP_ON_OFF_MESSAGE_ empty POWER...ON/OFF 19 7 0 10 -262144 -260097 -128992 1 1; #N canvas 649 312 450 300 POWER 0; #X obj 19 15 tgl 15 0 empty DSP_ON_OFF_MESSAGE_ empty 17 7 0 10 -262144 -1 -1 1 1; #X msg 19 36 \; pd dsp \$1; #X connect 0 0 1 0; #X restore 625 656 pd POWER; #N canvas 0 22 450 300 (subpatch) 0; #X array Wave 64 float 0; #X coords 0 1 63 -1 256 140 1; #X restore 21 38 graph; #N canvas 0 22 450 300 (subpatch) 0; #X array Amplitude 64 float 0; #X coords 0 1 63 0 256 140 1; #X restore 326 38 graph; #N canvas 0 22 450 300 (subpatch) 0; #X array Phase 64 float 0; #X coords 0 3.14159 63 -3.14159 256 140 1; #X restore 630 38 graph; #N canvas 812 458 518 269 OSCILLATOR 0; #X obj 341 23 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X msg 341 45 set \$1 1 1; #X obj 341 70 block~; #X obj 25 26 osc~; #X obj 130 26 osc~; #X obj 25 9 nbx 5 14 -1e+37 1e+37 0 0 empty WAVE_1_FREQUENCY_MESSAGE_ Wave_1_Frequency 0 -8 0 10 -262144 -1 -1 2637.18 256; #X obj 130 9 nbx 5 14 -1e+37 1e+37 0 0 empty WAVE_2_FREQUENCY_MESSAGE_ Wave_2_Frequency 0 -8 0 10 -262144 -1 -1 6773.57 256; #X obj 25 156 tabsend~ Wave_1; #X obj 130 46 tabsend~ Wave_2; #X obj 79 133 tabsend~ Wave; #X obj 79 79 /~ 2; #N canvas 810 50 516 381 FFT 0; #X obj 223 31 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X msg 223 53 set \$1 1 1; #X obj 223 78 block~; #X obj -176 74 rfft~; #X obj 41 163 expr~ atan2($v2 \, $v1); #X obj 41 182 tabsend~ Phase; #X obj -176 264 tabsend~ Amplitude; #X obj -176 12 inlet~; #X obj 133 46 sig~; #N canvas 802 219 386 284 WINDOW 0; #N canvas 0 22 450 300 (subpatch) 0; #X array Window 64 float 0; #X coords 0 1 63 0 140 140 1; #X restore 10 16 graph; #X obj 160 17 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 64 256; #X obj 160 67 samplerate~; #X obj 160 92 /; #X obj 160 146 osc~; #X obj 160 39 t b f b; #X msg 199 117 0; #X msg 284 42 set \$1 1 1; #X obj 284 67 block~; #X obj 160 221 tabsend~ Window; #X obj 160 169 *~ -0.46; #X obj 160 196 +~ 0.54; #X connect 1 0 5 0; #X connect 1 0 7 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 10 0; #X connect 5 0 2 0; #X connect 5 1 3 1; #X connect 5 2 6 0; #X connect 6 0 4 1; #X connect 7 0 8 0; #X connect 10 0 11 0; #X connect 11 0 9 0; #X restore 212 248 pd WINDOW; #X obj -161 33 tabreceive~ Window; #X obj -176 54 *~; #X obj -177 244 expr~ sqrt($v1 * $v1 + $v2 * $v2) / sqrt($v3); #X connect 0 0 1 0; #X connect 0 0 8 0; #X connect 1 0 2 0; #X connect 3 0 4 0; #X connect 3 0 12 0; #X connect 3 1 4 1; #X connect 3 1 12 1; #X connect 4 0 5 0; #X connect 7 0 11 0; #X connect 8 0 12 2; #X connect 10 0 11 1; #X connect 11 0 3 0; #X connect 12 0 6 0; #X restore 100 107 pd FFT; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 3 0 7 0; #X connect 3 0 10 0; #X connect 4 0 8 0; #X connect 4 0 10 0; #X connect 5 0 3 0; #X connect 6 0 4 0; #X connect 10 0 9 0; #X connect 10 0 11 0; #X restore 748 659 pd OSCILLATOR; #X obj 502 613 bng 15 250 50 0 SET_DEFAULTS_MESSAGE_ empty SET_DEFAULTS 19 7 0 10 -262144 -260097 -128992; #N canvas 0 22 450 300 (subpatch) 0; #X array Wave_1 64 float 0; #X coords 0 1 63 -1 256 140 1; #X restore 21 220 graph; #N canvas 0 22 450 300 (subpatch) 0; #X array Wave_2 64 float 0; #X coords 0 1 63 -1 256 140 1; #X restore 21 415 graph; #X obj 24 360 hsl 251 15 1 22050 0 0 WAVE_1_FREQUENCY_MESSAGE_ WAVE_1_FREQUENCY_INITIALIZE_MESSAGE_ Wave_1_Frequency 5 7 0 10 -228856 -260097 -128992 2989 1; #X obj 24 555 hsl 251 15 1 22050 0 0 WAVE_2_FREQUENCY_MESSAGE_ WAVE_2_FREQUENCY_INITIALIZE_MESSAGE_ Wave_2_Frequency 5 7 0 10 -228856 -260097 -128992 7679 1; #N canvas 938 500 331 222 DSP_BLOCK_SIZE 0; #X obj 27 -46 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_PRE_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE 0 -8 0 10 -262144 -1 -1 6 256; #X obj 27 51 nbx 5 14 -1e+37 1e+37 0 0 DSP_BLOCK_SIZE_MESSAGE_ empty empty 0 -8 0 10 -262144 -1 -1 64 256; #X obj 27 -26 expr pow(2 \, int($f1)); #X connect 0 0 2 0; #X connect 2 0 1 0; #X restore 625 674 pd DSP_BLOCK_SIZE; #X obj 20 652 hsl 95 15 6 15 0 0 DSP_PRE_BLOCK_SIZE_MESSAGE_ DSP_BLOCK_SIZE_INITIALIZE_MESSAGE_ DSP_BlOCK_SIZE 5 8 0 10 -262144 -260097 -128992 0 1; #X obj 120 653 nbx 5 14 -1e+37 1e+37 0 0 empty DSP_BLOCK_SIZE_MESSAGE_ empty 0 -8 0 10 -228856 -128992 -1 64 256;

2011年12月4日日曜日

Purge it !

現在非使用中
Macを長時間あれこれ使っていますと、現在非使用中のメモリがどんどん溜まっていきます。この領域を解放するための方法を探していましたが、デベロッパツールをインストールすると入る /usr/bin/purge が強力です。

user# purge

とターミナルから引数なしで、待つこと数秒、奇麗に現在非使用中メモリを解放してくれます。


エージェント化
たいした手間ではありませんので、気づいたときにターミナルから実行してやればよいのでしょうが、定期的に実行するには launchd にエージェントとして登録してやります。

plist 形式のファイルで適当にキーを指定してやり、用途に応じた場所(今回は ~/Library/LaunchAgents )に保存してやれば、起動時にlaunchd にエージェントとして登録されます。詳しくは man launchd.plist(5) を。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Label</key>
 <string>com.apple.purge</string>
 <key>ProgramArguments</key>
 <array>
  <string>/usr/bin/purge</string>
 </array>
 <key>StartInterval</key>
 <integer>10800</integer>
</dict>
</plist>

2011年11月27日日曜日

IMP, SEL, Method

IMP
まず IMP です。メソッド実装の先頭部分を指すポインタです。

This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.
IMP はメソッドを実装する関数の先頭部分を指すポインタです。この関数は現在の CPU アーキテクテャのために実装された標準 C の呼出規約(calling convention)を使います。最初の引数は self(クラスの特定の具体的なインスタンスのためのメモリ、クラスメソッドのためのメモリ、メタクラスを指すポインタのためのメモリ)へのポインタです。2番目の引数はメソッドセレクタです。メソッドの引数は以下の通り。


SEL
そして SEL です。セレクタを表現する構造体で Opaque Type です。

Method selectors are used to represent the name of a method at runtime. A method selector is a C string that has been registered (or “mapped“) with the Objective-C runtime. Selectors generated by the compiler are automatically mapped by the runtime when the class is loaded.

You can add new selectors at runtime and retrieve existing selectors using the function sel_registerName.

When using selectors, you must use the value returned from sel_registerName or the Objective-C compiler directive @selector(). You cannot simply cast a C string to SEL.
メソッドのセレクタはランタイムでメソッドの名前表現として使われます。メソッドのセレクタは Objective-C に登録(またはマッピング)されている C 文字列です。コンパイラによって生成されたセレクタは、クラスがロードされるとき、自動的にランタイムによってマッピングされます。

実行時に新しいセレクタを追加し、sel_registerName 関数を使って存在しているセレクタを取得できます。

セレクタを使うとき、sel_registerName が返す値か、Objective-C のコンパイラディレクティブ @selector() を使わなければなりません。単純に C 文字列を SEL にキャストすることはできません。


Method
Method はクラスで定義されているメソッドを表現する構造体で Opaque Type です。リファレンスには

typedef struct objc_method *Method;
としかありませんが runtime.h にはさらに
struct objc_method {
    SEL method_name                                          OBJC2_UNAVAILABLE;
    char *method_types                                       OBJC2_UNAVAILABLE;
    IMP method_imp                                           OBJC2_UNAVAILABLE;
}
とあります。OBJC2_UNAVAILABLE は Objective-C 2.0 では無効ということのようで、Objective-C 2.0 の環境ではこの構造体に直接アクセスはできません。Method 構造体にのデータにアクセスするには専用(method_*)のランタイム関数を使ってやればよしです。

めも
http://opensource.apple.com/

2011年11月22日火曜日

Method Swizzling

Mac OSX で NSColor -> CGColor の変換をよく使いますが NSColor は CGColor を返すメソッドがありません(*1)せめて NSColor のメソッドが CGColor を返してくれるようになったら嬉しい。そんなわけで NSColor が CGColor を返してくれるようにカテゴリで拡張します。まずはソースコードから。

*1 NSColor のメソッドに - (CGColorRef)CGColor が追加されました。10.8 以降 使用できます。

NSColor+CGColor.h
#import <Foundation/Foundation.h>

@interface NSColor (CGColor)
- (CGColorRef)CGColor;
@end


NSColor+CGColor.m
#import "NSColor+CGColor.h"
#import <objc/runtime.h>

@interface NSColor (Swizzling)

- (void)methodToExchangeImplementation;
- (void)preDealloc;

@end

@interface NSColor (Accessor)

- (void)initializeCGColorCollection;
- (void)releaseColorCollection;
- (void)setCGColorRef:(CGColorRef)colorRef;

@end

@implementation NSColor (Swizzling)

static IMP PRE_DEALLOC_IMPLEMENTATION = NULL;
static IMP DEALLOC_IMPLEMENTATION = NULL;

- (void)methodToGetImplementation {
    
    // メソッド構造体を取得する
    Method preDealloc = class_getInstanceMethod([self class], @selector(preDealloc));
    Method dealloc = class_getInstanceMethod([self class], @selector(dealloc));
    
    // メソッド構造体からメソッド実装を取得する
    PRE_DEALLOC_IMPLEMENTATION = method_getImplementation(preDealloc);
    DEALLOC_IMPLEMENTATION = method_getImplementation(dealloc);
    
}

- (void)methodToExchangeImplementation {
    
    if (PRE_DEALLOC_IMPLEMENTATION == NULL || DEALLOC_IMPLEMENTATION == NULL) {
        
        [self methodToGetImplementation];
        
    }
    
    // メソッド構造体を取得する
    Method preDealloc = class_getInstanceMethod([self class], @selector(preDealloc));
    Method dealloc = class_getInstanceMethod([self class], @selector(dealloc));
    
    // メソッドの実装を互いに入れかえる
    method_exchangeImplementations(preDealloc, dealloc);
    
}

- (void)preDealloc {
    
    // 辞書に CGColorRef を加えたオブジェクトは dealloc の前に解放する。
    [self setCGColorRef:NULL];
    [self releaseColorCollection];
    
    // dealloc を実装から呼ぶ。
    DEALLOC_IMPLEMENTATION(self, _cmd);

}
@end

@implementation NSColor (Accessor)

static NSMutableDictionary *CGColorCollection = nil;

- (void)initializeCGColorCollection {
    
    @synchronized (self) {
        
        if (!CGColorCollection) {
            
            CGColorCollection = [[NSMutableDictionary dictionary] retain];
            [self methodToExchangeImplementation];
        }
    }
}

- (void)releaseColorCollection {
    
    @synchronized (self) {
        
        if ([CGColorCollection count] == 0) {
            
            [CGColorCollection release];
            CGColorCollection = nil;
            
            [self methodToExchangeImplementation];
        }
    }
}

- (void)setCGColorRef:(CGColorRef)newColorRef {
    
    NSString *aKey = [NSString stringWithFormat:@"%p",self];
    
    @synchronized (self) {
        
        NSValue *value = [CGColorCollection valueForKey:aKey];
        
        if (value) {
            
            CGColorRef colorRef = (CGColorRef )[value pointerValue];
            [CGColorCollection removeObjectForKey:aKey];
            CGColorRelease(colorRef);
            
        }
        
        if (newColorRef != NULL) {
            
            [CGColorCollection setValue:[NSValue valueWithPointer:newColorRef]
                                 forKey:aKey];
        } 
    }
}
@end

@implementation NSColor (CGColor)
- (CGColorRef)CGColor {
    
    [self initializeCGColorCollection];
    
    // 現在のカラーの情報を取得する。
    NSColorSpace *colorSpace = [self colorSpace];
    size_t numberOfComponents = (size_t)[self numberOfComponents];
    CGFloat *components = (CGFloat *)calloc(numberOfComponents, sizeof(CGFloat));
    [self getComponents:components];
    
    // CGColorRef を生成する。
    CGColorRef colorRef = CGColorCreate([colorSpace CGColorSpace], components);
    free(components);
    
    // 自身をキーに生成した CGColorRef を辞書に加える。
    [self setCGColorRef:colorRef];
    
    return colorRef;
}
@end

こう考えてみた
  1. 単に NSColor からCGColor オブジェクトのインスタンスを生成するのでなく、NSColor の寿命に応じて 生成した CGColor の寿命もシンクロさせる。
  2. カテゴリはインスタンス変数の追加が出来ないので CGColor オブジェクトを適当なスコープ内に定義したグローバル変数で管理する。
生成した CGColor を個別に解放してやるのはスマートではないと思ったので、NSColor の寿命に応じて生成した CGColor の寿命もシンクロさたいと思いました。そうすると、どのタイミングで CGColor オブジェクトを解放するかですが、インスタンスの参照カウンタが 0 になると -(void) dealloc が自動で呼ばれることを利用して、ランタイム API で CGColor が生成されているあいだ -(void) dealloc の実装を -(void) preDealloc の実装で入れかえることで解決します。

preDealloc で擬似的なクラス変数に見立てた CGColorCollection を管理してやります。CGColorCollection が CGColor を持たなければメソッドの実装を元に戻してやります。ランタイムは NSColor の dealloc だと思って preDealloc を呼出しているので、最終的に本来呼ばれるべき dealloc を実装から直接呼んでやります。

2011年11月21日月曜日

It Is Possible To Detach My Mind from Main Thread

NSThreadの
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
について。

For non garbage-collected applications, the method aSelector is responsible for setting up an autorelease pool for the newly detached thread and freeing that pool before it exits. Garbage-collected applications do not need to create an autorelease pool.

The objects aTarget and anArgument are retained during the execution of the detached thread, then released. The detached thread is exited (using the exit class method) as soon as aTarget has completed executing the aSelector method.

If this thread is the first thread detached in the application, this method posts the NSWillBecomeMultiThreadedNotification with object nil to the default notification center.

ガベージコレクトされないアプリケーションでは、aSelector で与えるメソッドが新たに切り離されたスレッドのために、自動解放プールを設定して、セレクタの実行が終了する前にプールを解放する責任があります。ガベージコレクトされるアプリケーションは自動解放プールを作成する必要はありません。

切り離されたスレッドを実行している間 aTarget と anArgument が与えるオブジェクトは保持され、そのあと解放されます。切り離されたスレッドは aTarget オブジェクトの aSelector で与えるメソッドが完了するとすぐに(クラスメソッドの + (void)exit を使用して)終了します。

このスレッドがアプリケーションで最初に切り離されたスレッドの場合、このメソッドはデフォルトの通知センタに nil オブジェクトをともなって NSWillBecomeMultiThreadedNotification を投函します。


つまり
ガベージコレクションをしないアプリケーションでは、指定したセレクタ内で、自動解放プールの管理をしなさいねとのこと。

例えば
- (IBAction)saveData:(id)sender {
    
    [NSThread detachNewThreadSelector:@selector(saveBitmap)
                                                            toTarget:bitmapController
                                                       withObject:nil];
}
みたいなのがあって、ターゲットのオブジェクトでは
- (void)saveBitmap {
    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    /* 処理 */
    [pool drain];

}
を実装します。

また、10.5 以降ではこのクラスメソッドだけでなく NSThread のインスタンスが生成できるようになりました。NSOperation と同様の制御が可能です。

2011年11月7日月曜日

NSProgressIndicator on Sheet

NSProgressIndicator をシート上で動かそうとしたときに動きませんでした。

This method runs the modal event loop for the specified sheet synchronously. It displays the sheet, makes it key, starts the run loop, and processes events for it. While the application is in the run loop, it does not respond to any other events (including mouse, keyboard, or window-close events) unless they are associated with the sheet. It also does not perform any tasks (such as firing timers) that are not associated with the modal run loop. In other words, this method consumes only enough CPU time to process events and dispatch them to the action methods associated with the modal window.

このメソッドは指定されたシートのためのモーダル・イベント・ループを同期的に実行します。表示するシートをキーウィンドウにして、実行ループを開始します。そして、そのためのイベントを処理します。アプリケーションが実行ループ中のあいだ、シートに関連付けされてない限り、他のどんなイベント(マウス、キーボード、またはウィンドウ-クローズ・イベントを含む)にも応答しません。また、モーダル実行ループに関連付けられていないどんな(タイマー発動のような)タスクも実行しません。つまり、このメソッドはイベントを処理するために必要なCPU時間を費し、それらをモーダル・ウィンドウに関連付けられたアクション・メソッドへ送ります。

ということで、シート上のインジケータの更新を反映させるには、
    for (NSInteger index = 0; index < 1000; index++) {

        [indicator incrementBy:1.0];
        [indicator displayIfNeeded];
        
    }
ウィンドウとかビューとかに直接 display* を送信してやります。

2011年11月3日木曜日

Sometimes Talk About The Past...

♪ 時には昔の話をしようか ♪

そんな気分のときってあると思います。 クラスメソッドの initialize を実装してみましたが2回呼ばれているようです。10.6 Xcode 3.2.6 の話。

If a particular class does not implement initialize, the initialize method of its superclass is invoked twice, once for the superclass and once for the non-implementing subclass. If you want to make sure that your class performs class-specific initializations only once, implement initialize as in the following example:

特定のクラスが initialize を実装していない場合、スーパークラスの initialize メソッドは2回呼出されます。スーパークラスが1回と initialize を実装していないサブクラスが1回です。クラスが一度だけのクラス固有の初期化を実行することを確実にするには、次の例のように初期化を実装します。

@implementation MyClass
+ (void)initialize {
    if ( self == [MyClass class] ) {
        /* put initialization code here */
    }
}

実際この例のように実装してみたら呼出しが1回になりました。2011-09-08 に改訂されている NSObject Class Reference での initialize ではこの記述がなかったので、10.7 Xcode 4 では変更されているのかも。

ところで
もともと NSUserDefaults を使って NSRegistrationDomein にアプリケーションの初期値を設定しようと思っていました。

To register the application’s default behavior, you get the application's shared instance of NSUserDefaults and register default values with it. A good place to do this is in the initialize method of the class that uses the default. The following example registers the value “YES” for the default named “DeleteBackup”.
User Defaults Programming Topics "Setting a Default in the NSRegistrationDomain"

アプリケーションのデフォルトの動作を登録するために、NSUserDefaults の共有インスタンスを取得し、デフォルト値を登録します。これを行うのに良い場所は、デフォルト値を使用するクラスの initialize メソッドです。次の例は DeleteBackup という名前で YES の値を登録します。

+ (void)initialize {
 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *appDefaults = [NSDictionary
        dictionaryWithObject:@"YES" forKey:@"DeleteBackup"];
 
    [defaults registerDefaults:appDefaults];
}

とありましたが、この Topics は 2011-10-12 で更新されて Preferences and Settings Programming Guide という名前になりました。そしてこの記述はなくなりました。

♪ 今でも 同じように 見果てぬ夢を描いて 走り続けているよね どこかで ♪

2011年10月31日月曜日

Loading Objective-C Classes

NSBundle でアプリケーションバンドル内のクラスをロードします。NSBundle のロードのためのメソッドは Objective-C で書かれたのクラスのみで C++ その他の言語で書かれたものは使用できません。

- (void)loadClass {

    Class foo;
    id bar;
    NSBundle *bundle = [NSBundle mainBundle];

    if ( foo = [bundle classNamed:@"Foo"] ) {
        bar = [[foo alloc] init];
    }

}

SyntaxHighlighter on Blogger


Blogger に SyntaxHighlighter をホスティングで導入しましたが、細かいスタイルの変更はどうしたらよいのでしょうか? 直接サーバにインストールして使用している場合は "shCoreDefault.css" を編集しているようです。しかしホスティングではそうはまいりません。Blogger ではどうするか?

テンプレート -> HTMLの編集

で解決しようと思いましたら、直接HTMLを編集するより、よかったらテンプレートデザイナーを使ってね、と出てきました。そこで

テンプレート -> カスタマイズ -> アドバンス -> CSSの追加

/* SyntaxHighlighter 行ごとの色の変更 */
.syntaxhighlighter .line.alt2 {
  background-color: #f7f7f7 !important;
}

/* SyntaxHighlighter 行番号とソースコードの間の線の幅と色*/
.syntaxhighlighter .gutter .line {
  border-right: 3px solid #ededed !important;
}
と記述しましたとさ。

2011年7月29日金曜日

イメージを描画する(11.3)

bpf のフィルタを設定したい。そこで bpf(4) を見ます。オペコード、アキュームレータ、インデックスレジスタ... アセンブリ言語?疑似マシンへの命令は僕には難しすぎます。そんな僕のために libpcap は疑似マシン命令を手軽にコンパイルしてくれるということなので頼ります。

/*事前に/dev/bpf* はオープンされていて、ネットワークインターフェイス(struct ifreq ifr)がアタッチされている。*/

    char errorBuffer[PCAP_ERRBUF_SIZE];
    bpf_u_int32 mask;
    bpf_u_int32 net;

    if ((pcap_lookupnet(ifr.ifr_name, &net, &mask, errorBuffer)) == -1 ) {
        fprintf(stderr,"pcap_lookupnet:%s",errorBuffer);
        net = 0;
        mask = 0;
    }

    u_int dataLinkType;
    u_int bufferLength;

    ioctl(bpf, BIOCGDLT, &dataLinkType);
    ioctl(bpf, BIOCGBLEN, &bufferLength);

    pcap_t *tmpHandle = pcap_open_dead(dataLinkType, bufferLength);

    if (!tmpHandle) {
        fprintf(stderr,"pcap_open_dead:NULL");
    }

    struct bpf_program *bpfProgram = (struct bpf_program *)malloc(sizeof(struct bpf_program));
    const char *filterExpression = "ether proto \\ip";
    int optimize = 0;

    if (pcap_compile(tmpHandle,
                     bpfProgram,
                     filterExpression,
                     optimize,
                     mask) == -1 ) {
        fprintf(stderr,"pcap_compile:%s",pcap_geterr(tmpHandle));
    }

    pcap_close(tmpHandle);
    
    ioctl(bpf, BIOCSETF, bpfProgram);
    
    pcap_freecode(bpfProgram);

2011年7月19日火曜日

SyntaxHighlighter on Blogger

ソースコードが見にくいので SyntaxHighlighter を Blogger で使えるようにします。

SyntaxHighlighter -> integration から ここのサイトを参考にして Objective-C を加えたのが以下。デザイン-> HTMLの編集で <HEAD> の前に挿入。

<!--SYNTAX HIGHLIGHTER BEGINS-->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'></script>
<script src='http://www.undermyhat.org/blog/wp-content/uploads/2009/09/shBrushObjectiveC.js' type='text/javascript'></script>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
</script>
<!--SYNTAX HIGHLIGHTER ENDS-->

C
int main (int argc, char const *argv[])
{
    printf("Hello world!");
    return 0;
}


Objective-C
#import <Cocoa/Cocoa.h>
@interface TestObject : NSObject
{
    NSMutableArray *testArray;
}
@property (readonly) NSMutableArray *testArray;
- (void)setTestArray:(NSMutableArray *)array;

行ごとに色を変る方法は確認中。

2011年7月15日金曜日

イメージを描画する(11.2)

インターフェイスと bpf デバイスファイルのアタッチ

めも
///// bpf デバイスファイルのオープン /////
    NSArray *devices;
    NSString *deviceFile = @"/dev/bpf";
    int bpf;

    [deviceFile completePathIntoString:nil
                         caseSensitive:YES
                      matchesIntoArray:&devices
                           filterTypes:nil];
      
    for (NSString *device in devices) {
        bpf = open([device UTF8String],O_RDONLY,0);
        
        if (bpf != -1 ) {
            break;
        }
    }

// 使用するネットワークインターフェイスを用意する e.g "en0"
    struct ifreq ifr;
    bzero(ifr.ifr_name, sizeof(char) * IFNAMSIZ);
    strncpy(ifr.ifr_name, argv[1], IFNAMSIZ);

// デバイスファイルとネットワークインターフェイスを接続、設定する
    u_int isImmediately = 1;
    u_int isIO = 0;             // Input only;
    u_int bufferLength = (u_int)([[NSString stringWithCString:argv[2]
                                            encoding:NSUTF8StringEncoding] intValue]

    ioctl(bpf, BIOCSBLEN, &bufferLength); // 長さ
    ioctl(bpf, BIOCSETIF, &ifr);  // 接続
    ioctl(bpf, BIOCIMMEDIATE, &isImmediately); // すぐに書出す
    ioctl(bpf, BIOCSSEESENT, &isIO); // インプットのみ
あとは read(2) でデバイスファイルから読込む。
また読込みは bpf(4) Mac OS X Man page より bpf_hdr について。
The following structure is prepended to each packet returned by read(2):
"以下の構造体(bpf_hdr)はread(2) によって戻される各パケットの先頭に追加されます。"

Additionally, individual packets are padded so that each starts on a word boundary.  This requires that an application has some knowledge of how to get from packet to packet.  The macro BPF_WORDALIGN is defined in to facilitate this process.  It rounds up its argument to the nearest word aligned value (where a word is BPF_ALIGNMENT bytes wide).
p = (char *)p + BPF_WORDALIGN(p->bh_hdrlen + p->bh_caplen)

考え中。

// kernel -> bpf デバイスファイルへのデータコピーの状態
        struct bpf_stat status;
        ioctl(bpf, BIOCGSTATS,&status);
        NSLog(@"receive:%d, drop:%d",status.bs_recv, status.bs_drop);

bs_drop: パケットトラフィックがついていっていないとカーネルがドロップする。その数。

2011年7月10日日曜日

イメージを描画する(11.1)

ネットワークインターフェイスの一覧を取得したい。
めも

/////////////// ネットワークインターフェイスの取得 ///////////////
     int socketFD,length, lastLength;
    char *buffer;
    struct ifconf ifc;
    
    socketFD = socket(AF_INET, SOCK_DGRAM, 0);
    lastLength = 0;
    length = sizeof(struct ifreq) * 100;
    NSLog(@"length:%d",length);
    
    for (; ;) {
        
        buffer = (char *)calloc(length, sizeof(char));
        ifc.ifc_len = length;
        ifc.ifc_ifcu.ifcu_buf = buffer;
        
        if ( ioctl(socketFD, SIOCGIFCONF, &ifc) < 0) {
            int erroNumber = errno;
            NSLog(@"%s",strerror(erroNumber));
        } 
        else {
            
            if (ifc.ifc_len == lastLength) {
                break;
            }
            
            lastLength = ifc.ifc_len;
        }
        
        length += sizeof(struct ifreq) * 10;
        free(buffer);
    }
    
    struct ifreq *ifr = (struct ifreq *)buffer;
    int next = 0;
    /////////////// 表示してみる ///////////////
    while (ifr < (struct ifreq *)(buffer + lastLength)) {
        
        ifr = (struct ifreq *)(buffer + next);
        NSLog(@"interface:%s",ifr->ifr_name);
        next += IFNAMSIZ + ifr->ifr_ifru.ifru_addr.sa_len;
        
    }
    free(buffer);
    close(socketFD);
同じのがいっぱい出た。

2011年6月28日火曜日

イメージを描画する(10)

あなたの瞳の色が僕の中でどんな色で見えているのか伝えたい、写真家にもそんなときってあると思います。というわけでこんなものを作ります。


このイメージを
こう表示する。



-- 途中です。改訂します。 --

/* めも
RGB のカラー・ガモット(color gamut)の各頂点を情報(三刺激値?)を取得する。
プロファイルのデータから rXYZ, gXYZ, bXYZ を得る。

Specification ICC.1:2004-10-10 (Profile Version 4.2.0.0)
redMatrixColumnTag, greenMatrixColumnTag and blueMatrixColumnTag は XYZType.
     -- XYZType Encoding --
     0-3    4byte   'XYZ ' type sigunature.
     4-7    4Byte   reserved, must be set to 0.
     8-end    -     an array of XYZ number. XYZNumber
    
     -- XYZ Number --
     0-3    4Byte   CIE X   s15Fixed16Number
     4-7    4Byte   CIE Y   s15Fixed16Number
     8-11   4Byte   CIE Z   s15Fixed16Number
    
     -- s15Fixed16Number --
     Number                 Encoding
     -32768.0               80000000h
     0                      00000000h
     1.0                    00010000h
     32767 + (65535/65536)  7FFFFFFFh
前半分が符号付き整数、後ろ半分が小数だけど、整数値を65536で割った値。つまり
iiiiiiiiiiiiiiii + ffffffffffffffff / 65536

7 Profile requirements
a)    All profile data shall be encoded as big-endian,

ColorSync Manager API 
CMGetPartialProfileElement //ColorSyncDeprecated.h 非推奨
 elementData の値がリトルエンディアンで戻ったので EndianS32_BtoN にかけた。

*/

2011年6月20日月曜日

イメージを描画する(9)

あなたの瞳は世界をどんなふうに見るの?奇麗な瞳をみられたら写真家にもそんな気持ちになるときがあると思います。というわけで、こんなものをつくります。


Photoshop(CS3)では ”色の校正” プレビュー(5.0.3)では ”プロファイルを使ってソフトプルーフ” 、つまりソフトプルーフ機能を単独で実装します。

NSBitmapImageRep
表示だけのシステムなので、なにかないか探してみますとこんなものがありました。

- (NSBitmapImageRep *)bitmapImageRepByConvertingToColorSpace:(NSColorSpace *)targetSpace
                                                           renderingIntent:(NSColorRenderingIntent)renderingIntent

すてき。長いです。画像を描画意図(rendering intent)で別の色空間に変換してくれます。ここに色校正に使うディスプレイ・プロファイルとアウトプット・プロファイルからカラースペースを作って渡してやればよさそうです。なお 10.6 以降です。

NSColorSpace
NSColorSpace にはプロファイルのクラスごとにカラースペースを生成してくれるメソッドがないので

- (id)initWithColorSyncProfile:(void *)prof

を使ってColorSync プロファイルから作成してやれば良さそうです。引数が (void *)prof となっていますが、リファレンスは CMProfileRef わたすべしとなっています。なるほど。

ColorSync Manager API
目的は CMProfileRef を取得することです。

CMError CMOpenProfile (
   CMProfileRef *prof,
   const CMProfileLocation *theProfile
);

第1引数は戻ったときにプロファイルがはいります。なので第2引数の CMProfileLocation を取得して渡してやればよいですが、長旅になりそうな予感!

少し寄り道 CMIterateColorSyncFolder
インストースされているプロファイルの情報を提供してくれる API はないものでしょうか。そんな僕のために CMIterateColorSyncFolder 関数がありました。すべての利用可能なプロファイルからプロファイルごとの情報を確認できます。

CMError CMIterateColorSyncFolder (
   CMProfileIterateUPP proc,
   UInt32 *seed,
   UInt32 *count,
   void *refCon
);

第1引数は CMIterateColorSyncFolder ルーチンのなかで呼出されるコールバック関数のポインタになります。

第2引数はキャッシュの設定です。CMIterateColorSyncFolder 初めて呼出すときは0をセットしたポインタを渡せとあります。内部の seed と一致しなかったな場合はプロファイルごとに一度のコールバックを呼出すとあります。

第3引数は戻ってきたときに利用可能なプロファイルの数が入れられます。

第4引数は任意のデータへのポインタを指定します。この値は第1引数のコールバックが呼出されるたびに渡されます。なのでコールバック内で参照する必要のあるデータがある場合は設定します。

今度は CMProfileIterateUPP!
CMIterateColorSyncFolder の第1引数 CMProfileIterateUPP は

typedef CMProfileIterateProcPtr CMProfileIterateUPP;

となっていて CMProfileIterateProcPtr は

typedef OSErr (*CMProfileIterateProcPtr)
(
   CMProfileIterateData * iterateData,
   void * refCon
);

です。第1引数にはプロファイルに関連するデータ構造体です。第2引数にはCMIterateColorSyncFolder の第4引数で設定したデータへのポインタがそのままやってきます。

CMProfileLocation を求めて
CMProfileIterateData はどうなっているのでしょうか。

struct CMProfileIterateData {
   UInt32 dataVersion;
   CM2Header header;
   ScriptCode code;
   Str255 name;
   CMProfileLocation location;
   UniCharCount uniCodeNameCount;
   UniChar * uniCodeName;
   unsigned char * asciiName;
   CMMakeAndModel * makeAndModel;
   CMProfileMD5 * digest;
};
typedef struct CMProfileIterateData CMProfileIterateData;

CMProfileLocation ありました。これを CMOpenProfile に渡してやれば CMProfileRef が取得できます。さらに CM2Header 構造体の

struct CM2Header {
   UInt32 size;
   OSType CMMType;
   UInt32 profileVersion;
   OSType profileClass;
   OSType dataColorSpace;
   OSType profileConnectionSpace;
   CMDateTime dateTime;
   OSType CS2profileSignature;
   OSType platform;
   UInt32 flags;
   OSType deviceManufacturer;
   UInt32 deviceModel;
   UInt32 deviceAttributes[2];
   UInt32 renderingIntent;
   CMFixedXYZColor white;
   OSType creator;
   char reserved[44];
};
typedef struct CM2Header CM2Header;

OSType profileClass でプロファイルのクラスの情報があります。

enum {
   cmInputClass = 'scnr',
   cmDisplayClass = 'mntr',
   cmOutputClass = 'prtr',
   cmLinkClass = 'link',
   cmAbstractClass = 'abst',
   cmColorSpaceClass = 'spac',
   cmNamedColorClass = 'nmcl'
};

cmDisplayClass と cmOutputClass を使ってプロファイルのクラスを選別できそうです。

それでは
戻り値のチェックをしていません。
DrawingImage_9_AppDelegate.h
#import <Cocoa/Cocoa.h>

@class DISourceImageView, DIProofImageView;

@interface DrawingImage_9_AppDelegate : NSObject  {
    NSWindow *window;
    
    DISourceImageView *srcView;
    DIProofImageView *proofView;
    
    NSTextField *srcColorSpaceField;
    
    NSBitmapImageRep *srcImage;
}

#pragma mark Accessor Method
@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet DISourceImageView *srcView;
@property (assign) IBOutlet DIProofImageView *proofView;
@property (assign) IBOutlet NSTextField *srcColorSpaceField;

#pragma mark Action Method
- (IBAction)openImage:(id)sender;
@end

DrawingImage_9_AppDelegate.m
#import "DrawingImage_9_AppDelegate.h"
#import "DISourceImageView.h"
#import "DIProofImageView.h"

@implementation DrawingImage_9_AppDelegate

#pragma mark init & dealloc
- (void) dealloc
{
    [srcImage release];
    [super dealloc];
}

#pragma mark Accessor Method
@synthesize window, srcView, proofView, srcColorSpaceField;

#pragma mark Inner Method
- (void)setViewsWithImage:(NSBitmapImageRep *)bitmapImage
{
    if (bitmapImage) {
        NSColorSpace *srcSpace = [bitmapImage colorSpace];
        [srcColorSpaceField setStringValue:[srcSpace localizedName]];
    }
    else {
        [srcColorSpaceField setStringValue:@""];
    }
    
    [srcView setImage:bitmapImage];
    [proofView setImage:bitmapImage];
}

#pragma mark Action Method
-(IBAction)openImage:(id)sender
{
    NSOpenPanel *opPanel = [NSOpenPanel openPanel];
    
    [opPanel setCanChooseFiles:YES];
    [opPanel setCanChooseDirectories:NO];
    [opPanel setAllowsMultipleSelection:NO];
    
    [opPanel beginSheetModalForWindow:window
                    completionHandler:^(NSInteger result){
                        
                        if (result == NSFileHandlingPanelOKButton) {
                            
                            if (srcImage != nil) {
                                [srcImage release];
                            }
                            
                            NSData *data = [NSData dataWithContentsOfURL:[opPanel URL]];
                            srcImage = [[NSBitmapImageRep alloc] initWithData:data];
                            
                            [self setViewsWithImage:srcImage];
                            
                        }
                        else {
                            // do nothing; 
                        }
                        
                    }];
}
@end

DISourceImageView.h
#import <Cocoa/Cocoa.h>

@interface DISourceImageView : NSView {

    NSBitmapImageRep *image;

}

#pragma mark Accessor Method
- (void)setImage:(NSBitmapImageRep *)bitmapImage;
@end

DISourceImageView.m
#import "DISourceImageView.h"

@implementation DISourceImageView

#pragma mark init & dealloc
- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

#pragma mark Drawing Method
- (void)drawRect:(NSRect)dirtyRect {
    
    if (image) {
        
        // ビューのサイズを取得
        CGSize viewSize = CGSizeMake([self bounds].size.width,
                                     [self bounds].size.height);
        
        // NSBitmapImageRep から CGImageRef を取得
        CGImageRef imageRep = [image CGImage];
        
        // 現在のグラフィクス・コンテキストを取得、変更するのでグラフィック状態を保存
        CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
        CGContextSaveGState(context);
        
        //描画意図を Absolute Colorimetric(絶対的な色域)に設定
        CGContextSetRenderingIntent(context, kCGRenderingIntentAbsoluteColorimetric);
        
        // 体裁を整えてイメージを描画
        CGFloat imageWidth = CGImageGetWidth(imageRep);
        CGFloat imageHeight = CGImageGetHeight(imageRep);
        
        CGFloat scale = imageHeight / imageWidth;
        
        BOOL isWide = (imageWidth >= imageHeight) ? YES : NO;
        
        if (isWide == YES) {
            
            CGFloat translate;
            translate = (viewSize.height - (viewSize.width * scale)) / 2.0;
            
            CGContextTranslateCTM(context, 0.0, translate);
            CGContextScaleCTM(context, 1.0, scale);
        }
        else {
            CGFloat translate;
            translate = (viewSize.width - (viewSize.height * (1.0 / scale))) / 2.0;
            
            CGContextTranslateCTM(context, translate, 0.0);
            CGContextScaleCTM(context, 1.0 / scale, 1.0);
            
        }
        
        CGContextDrawImage(context, CGRectMake(0.0,0.0,viewSize.width,viewSize.height), imageRep);
        
        // グラフィクス・コンテキストをもとに戻す。
        CGContextRestoreGState(context);
    }
    else {
        // do nothing;
    }
}

#pragma mark Accessor Method
- (void)setImage:(NSBitmapImageRep *)bitmapImage
{
    image = bitmapImage;
    [self setNeedsDisplay:YES];
}


@end

DIProofImageView.h
#import <Cocoa/Cocoa.h>

@interface DIProofImageView : NSView {

    NSPopUpButton *outputSpace;
    NSPopUpButton *intent;
    
    NSBitmapImageRep *image;
}

#pragma mark Accessor Method
@property (assign) IBOutlet NSPopUpButton *outputSpace;
@property (assign) IBOutlet NSPopUpButton *intent;
- (void)setImage:(NSBitmapImageRep *)bitmapImage;

#pragma mark Action Method
- (IBAction)selectedColorSpace:(id)sender;
- (IBAction)selectedRenderingIntent:(id)sender;
@end

DIProofImageView.m
#import "DIProofImageView.h"

#pragma mark Profile Iteration Callback Function
OSErr profileIterateProcPtr (CMProfileIterateData *iterateData, void *refCon)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSMutableArray *colorSpaces = refCon;

    // プロファイルのクラスを取得
    OSType profileClass = (*iterateData).header.profileClass;
    
    // クラスがアウトプット、ディスプレイに該当したら追加する。
    if (profileClass == cmOutputClass || profileClass == cmDisplayClass){

        // プロファイルからカラースペースを作成する。
        CMProfileRef prof;
        CMProfileLocation location = iterateData->location;
        
        // プロファイルを開く
        CMOpenProfile(&prof, &location);
        
        // プロファイルからカラースペースを作成
        NSColorSpace *colorSpace = [[NSColorSpace alloc] initWithColorSyncProfile:prof];
        [colorSpaces addObject:colorSpace];
        
        // もういらない。開いたプロファイルは閉じる。
        [colorSpace release];
        CMCloseProfile(prof);
        
    }
    
    [pool drain];
    return noErr;
}
#pragma mark -
@implementation DIProofImageView

#pragma mark init & dealloc
- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

#pragma mark awakeFromNib
- (void)awakeFromNib
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    // インストールされているプロファイルからカラースペースを作成して、Arrayに追加する。
    NSMutableArray *colorSpaces = [NSMutableArray array];
    CMIterateColorSyncFolder(profileIterateProcPtr, NULL, NULL, colorSpaces);
    
    // メニューを作成してポップアップボタンに設定する。
    NSMenu *outputMenu = [[NSMenu alloc] init];
    
    for (NSColorSpace *colorSpace in colorSpaces) {
        
        NSMenuItem *item = [[NSMenuItem alloc] init];
        
        // メニューアイテムにタイトルとカラースペースを設定、メニューに追加
        [item setTitle:[colorSpace localizedName]];
        [item setRepresentedObject:colorSpace];
        [outputMenu addItem:item];
        
        [item release];
    }
    
    [outputSpace setMenu:outputMenu];
    
    [outputMenu release];
    [colorSpaces removeAllObjects];

    
    // 描画意図(Rendering intent)をポップアップボタンに設定する。
    NSMutableDictionary *intentDic = [NSMutableDictionary dictionary];
    
    [intentDic setValue:[NSNumber numberWithInteger:1] forKey:@"Absolute Colorimetric"];
    [intentDic setValue:[NSNumber numberWithInteger:2] forKey:@"Relative Colorimetric"];
    [intentDic setValue:[NSNumber numberWithInteger:3] forKey:@"Perceptual"];
    [intentDic setValue:[NSNumber numberWithInteger:4] forKey:@"Saturation"];
    
    NSMenu *intentMenu = [[NSMenu alloc] init];
    
    for (NSString *key in [intentDic allKeys]) {
        
        NSMenuItem *item = [[NSMenuItem alloc] init];
        
        // メニューアイテムにタイトルとカラースペースを設定、メニューに追加
        [item setTitle:key];
        [item setRepresentedObject:[intentDic valueForKey:key]];
        [intentMenu addItem:item];
        
        [item release];
    }
    
    [intent setMenu:intentMenu];
    
    [intentMenu release];
    [intentDic removeAllObjects];
    
    [intent selectItemWithTitle:@"Perceptual"];
    
    [pool drain];
}

#pragma mark Drawing Method
- (void)drawRect:(NSRect)dirtyRect {
    
    if (image) {
        
        // 選択されているカラースペースと描画意図からビットマップを変換する
        NSColorSpace *colorSpace;
        NSColorRenderingIntent renderingIntent;
        NSBitmapImageRep *outputImage;
        
        colorSpace = [[outputSpace selectedItem] representedObject];
        renderingIntent = [[[intent selectedItem] representedObject] integerValue];
        outputImage = [image bitmapImageRepByConvertingToColorSpace:colorSpace
                                                    renderingIntent:renderingIntent];
        
        // ビューのサイズを取得
        CGSize viewSize = CGSizeMake([self bounds].size.width,
                                     [self bounds].size.height);
        
        // NSBitmapImageRep から CGImageRef を取得
        CGImageRef imageRep = [image CGImage];
        
        // 現在のグラフィクス・コンテキストを取得、変更するのでグラフィック状態を保存
        CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
        CGContextSaveGState(context);
        
        //描画意図を Absolute Colorimetric(絶対的な色域)に設定
        CGContextSetRenderingIntent(context, kCGRenderingIntentAbsoluteColorimetric);
        
        // 体裁を整えてイメージを描画
        CGFloat imageWidth = CGImageGetWidth(imageRep);
        CGFloat imageHeight = CGImageGetHeight(imageRep);
        
        CGFloat scale = imageHeight / imageWidth;
        
        BOOL isWide = (imageWidth >= imageHeight) ? YES : NO;
        
        if (isWide == YES) {
            
            CGFloat translate;
            translate = (viewSize.height - (viewSize.width * scale)) / 2.0;
            
            CGContextTranslateCTM(context, 0.0, translate);
            CGContextScaleCTM(context, 1.0, scale);
        }
        else {
            CGFloat translate;
            translate = (viewSize.width - (viewSize.height * (1.0 / scale))) / 2.0;
            
            CGContextTranslateCTM(context, translate, 0.0);
            CGContextScaleCTM(context, 1.0 / scale, 1.0);
            
        }
        
        [outputImage drawInRect:[self bounds]];
        
        // グラフィクス・コンテキストをもとに戻す。
        CGContextRestoreGState(context);
    }
    else {
        // do nothing;
    }
}

#pragma mark Accessor Method
@synthesize outputSpace, intent;

- (void)setImage:(NSBitmapImageRep *)bitmapImage
{
    image = bitmapImage;
    [self setNeedsDisplay:YES];
}

#pragma mark Action Method
- (IBAction)selectedColorSpace:(id)sender
{
    [self setNeedsDisplay:YES];
}
- (IBAction)selectedRenderingIntent:(id)sender
{
    [self setNeedsDisplay:YES];
}
@end

Interface Builder での作業



その他
指定したカラースペースに変換したビットマップを生成するのに ColorSync Manager API だけでやろうとするとけっこうめんどうです。NCWConcatColorWorld か CWConcatColorWorld を使って CMWorldRef を作成してやります。それを CWMatchBitmap にかけてやってビットマップを作成すれば良いと思います。また、この間に使用するいくつかの構造体を定義してやらなければなりません。