Maxオブジェクト開発技法

以下の情報は2004年1月時点でのIAMASの授業資料です。


Maxオブジェクト開発講座
2004.01.09 赤松正行

以下はOS X用Maxのベータ版SDK(sdk-beta-osx)に基づいている。

■開発ツール

Cycling'74 Max/MSP/Jitter
Metrowerks CodeWarrior
Apple ResEdit
Max/MSP SDK http://www.cycling74.com/products/dlmaxmspmac.html

* Maxオブジェクトには、OS9用68K用、OS 9用PowerPC版、OS9用FAT版、OS X用PowerPC版の4種類がある。
* 一部のOS9用PowerPC版/FAT版オブジェクトはOS Xでも動作する。
* 現時点のMaxはCFMオブジェクトしか扱えないので、CodeWarriorによって開発する。
* Project Builder/Xcodeが生成するMach-Oオブジェクトは利用できない。

■SDKの設定

SDKに含まれる「c74support」フォルダを「Metrowerks CodeWarrior」フォルダ(CodeWarrior IDEアプリケーションがあるフォルダ)にコピーする。

■オブジェクトのメイクと動作確認

(1) CodeWarriorを起動し、プロジェクトを開く。
(2) プロジェクトメニューの「メイク」を選ぶ。エラーがなければ「build-mac」フォルダにオブジェクトが作成される。
(OS 9用のオブジェクトは「build-classic」フォルダに作成される。)
(3) Maxを起動し、作成したオブジェクトを利用するパッチを実行する。
(「build-mac」フォルダにパッチを入れると良い。Maxのファイル・サーチパスに同名のオブジェクトがないこと。)

* サンプルの「maximum」は標準のオブジェクトなので、「externals」フォルダに存在するオブジェクトファイルを一時的に取り除いておくと良い。
* オブジェクトを修正した場合は、Maxを一旦終了させた後、再度Maxを起動することが必要。

■新規プロジェクトの作成

SDKに含まれる「SDKreadme.txt」ファイルの「Selecting and Using Project Templates」に従って、新規プロジェクトを作成する。

* 既存のサンプルを改造することも考えられるが、変更すべき箇所が多いのでかえって面倒かも。

■処理の概要

(「1. maximum」を題材として、日本語コメント付きソースコードあり)

◆メイン関数 main()【必須】
Max起動時などオブジェクトファイル読み込み時に呼び出される。
クラスとして必要な初期化などの設定を行う。
- クラスの設定を行う。setup()【必須】
- メッセージ処理関数を登録する。【ほぼ必須】
- オブジェクトリストへの登録やリソースのコピーなどを行う。

◆メッセージ処理関数 maximum_bang()など【ほぼ必須】
オブジェクトにメッセージが送られた時に対応する関数が呼び出される。
メッセージ処理関数の引数は、その登録によって異なる。

◆オブジェクト生成関数 maximum_new()【必須】
オブジェクト生成時に呼び出される。
インスタンスとして必要な初期化などの設定を行う。
- オブジェクトを生成する。newobject()【必須】
- アーギュメントの処理、インレット、アウトレットの作成などを行う。
(右から左への順序で。第1インレットはnewobject()が自動的に作成する。)
- 生成したオブジェクトへのポインタを関数の戻り値として返す。【必須】

■メッセージ処理関数の登録

ext_proto.hに定義されている以下の関数を用いる。

void addbang(method f); // bangメッセージ処理関数の登録
void addint(method f); // 整数メッセージ処理関数の登録
void addfloat(method f); // 実数メッセージ処理関数の登録
void addinx(method f, short n); // 第nインレットでの整数メッセージ処理関数の登録
void addftx(method f, short n); // 第nインレットでの実数メッセージ処理関数の登録
fはメッセージ処理関数へのポインタ
nはインレット番号(0始まり、第2インレットは1)

void addmess(method f, char *s, short type, ...); // 任意のメッセージ処理関数の登録
sはメッセージ文字列、typeはアーギュメントのデータタイプで任意の数で、最後は0で終える。

* オブジェクトがメッセージを受け取る時に、登録されたメッセージ処理関数に従って、メッセージやアーギュメントがチェックされ、一致しなければ自動的にエラーとなる。

■メッセージ処理関数への引数

整数メッセージ処理関数の場合、
void maximum_int(t_maximum *x, long n)
xはオブジェクト構造体へのポインタ
nは送られた整数そのもの

リストメッセージ処理関数の場合
void maximum_list(t_maximum *x, t_symbol *s, short ac, t_atom *av)
sはメッセージのシンボル(list)
acはリストの要素数
avはリストの最初の要素へのポインタ

■メッセージ処理関数の例

「jack n m」メッセージ、nとmは整数で、nは省略不可、mは省略可能とすると、
メッセージ処理関数のプロトタイプ宣言は、
void maximum_jack(t_maximum *x, long n, long m);
メッセージ処理関数の登録は、
addmess((method)maximum_jack, "jack", A_LONG, A_DEFLONG, 0);
となる。

■データタイプ

ext_mess.hに定義されている。

#define A_NOTHING 0 // 無(データはないことを示す)
#define A_LONG 1 // 整数
#define A_FLOAT 2 // 実数
#define A_SYM 3 // シンボル
#define A_OBJ 4 // オブジェクト、アーギュメントの配列(今後は使われない?)
#define A_DEFLONG 5 // デフォルト値が0である整数
#define A_DEFFLOAT 6 // デフォルト値が0.0である実数
#define A_DEFSYM 7 // デフォルト値が""であるシンボル
#define A_GIMME 8 // アーギュメントの配列、t_atomの配列であることをチェック
#define A_CANT 9 // タイプチェック不能/不要であるアーギュメント
#define A_SEMI 10 // 「;」
#define A_COMMA 11 // 「.」
#define A_DOLLAR 12 // 「$」

■データ構造

Maxのデータ(整数、実数、シンボル)はすべてt_atom(Atom)構造体で表されている。

union word // データ値の共用体
{
long w_long;
float w_float;
struct symbol *w_sym;
struct object *w_obj;
};

typedef struct atom // データの構造体
{
short a_type; // データタイプ
union word a_w; // データ値
} t_atom, Atom;

例:t_atom *data の場合、

値を参照するには、
if (data->a_type == A_LONG)
value = data->a_w.w_long;

整数を代入するには、
data->a_type = A_LONG;
data->a_w.w_long = 100;

■ソースコード・デバッグの方法

(1) CodeWarriorを起動し、プロジェクトを開き、プロジェクト・ウィンドウでターゲットを「debug」にする。
(2) プロジェクト・ウィンドウでデバッグするソースファイルのデバッグ欄にチェック(丸印)を入れる。
(3) 編集メニューの「debugの設定」を選び、設定ウィンドウのターゲットのランタイム設定を選び、ホストアプリケーションにMaxMSPアプリケーションを設定する。
(4) ソースコードにブレークポイントを設定する。
(5) プロジェクトメニューの「デバッグ」を選ぶ。(→MaxMSPアプリケーションが起動する)
(6) デバッグ中のオブジェクトを利用するパッチを実行する。(→ブレークポイントに達するとデバッガに切り替わる)
(7) デバッグを終えるにはMaxMSPアプリケーションを終了する。* オブジェクトが完成すれば、ターゲットを「release」にし、最終的なオブジェクト・ファイルをメイクする。