Chapter 5:
メッセージ

オブジェクトはメッセージに応答する形で動作します。通常、オブジェクトは数値(整数-int-や浮動小数-float)をインレットで受け取り、それらを処理し、他のメッセージをアウトレットから出力します。しかし、Maxのメッセージボックスオブジェクトを使って、文字列から始まる任意のメッセージをオブジェクトに送信することもできます。

さらに、Maxのメッセージボックスは、直接接続されていないオブジェクトにメッセージを送ることも可能です。セミコロンにシンボルを続けたものは、それ以降のメッセージの受信先になります。自分自身をこのシンボルにバインド(関連付け)しているオブジェクトであれば、どのようなオブジェクトでもメッセージを受信することができます(下記のシンボルデータ構造体に関する記述の中の、バインド(関連付け)の説明を参照して下さい。)。例えば、次のパッチにある、receive gooオブジェクトは bang メッセージを送信するメッセージボックスと直接接続されていないにもかかわらず、bang メッセージを受け取ることができ(そして、ボタンが明るくなり)ます。オブジェクトが作られる際、オブジェクトは自分自身をシンボルアーギュメント(この場合は goo )に結び付けます。

基本的な動作

通常、オブジェクトが数値によって何かの動作をするという「定義」は、左インレットで受信した整数(int メッセージ)に応答するメソッドの中になければなりません。一般的な規則では、Maxオブジェクトは bang メッセージを受信するたびに、左インレットで整数を受信した際に行う動作を、最後に受け取った値を使って繰り返し実行します。このような動作があなたのオブジェクトにとって理にかなったものである場合、受信した int メッセージをオブジェクト内に値として保存しておきたいと考えるでしょう。

オブジェクトの左端のインレット以外のインレットへ数値が渡されることによって、異なったメッセージを得ることができます。左端のインレットが int メッセージを与えるのに対して、他のインレットは in1in2 といったメッセージを渡します。(後で述べるような適当な設定を行ったと仮定した場合、in1は左から2番目のインレットを表し、in の次の数が増えるごとに右へ進みます。)

ほとんどの場合、左端のインレットはオブジェクトから値を出力したり、オブジェクトに何かの動作を行わせるために用い、他のインレットは動作を行うために必要な追加情報を保存するために用いたいと考えるでしょう。

例として、noteout オブジェクトを考えてみましょう。この左端のインレットは演奏される音のピッチを指定し、他のインレットはMIDIチャンネルとベロシティを指定します。noteout の内部の構造体はこのようなものです。

typedef struct noteout { t_object n_ob; short pitch, velocity, channel; } Noteout;

noteout オブジェクトは3つのインレットそれぞれについて、次のようなメソッドを持っています。

int ピッチの設定、現在持っているベロシティとMIDIチャンネルによるMIDIノートメッセージの送信
in1 ベロシティの設定
in2 MIDIチャンネルの設定

ちなみに、noteout のような3つのインレットをもつオブジェクトに 3つの整数から成るリストを送信した場合、Maxはリストを3つの別々のメッセージに分けます。そして、第1に3番目の数を in2 メッセージとして送信し、次に2番目の数を in1メッセージとして、最後に1番目の数を int として送信します。オブジェクトが list メッセージに対応するメソッドを持っている場合には、この動作は起こりません。(listメソッドについては、後で inlet_new を見ていく中で詳しく説明します。)

3つの整数に対応するメソッドを書いた後で、さらに bang に対応するメソッドを書く必要があります。これは、オブジェクトがその時点で保持しているピッチ、ベロシティ、MIDIチャンネルの値によってMIDIノートメッセージを送信するものです。

同様なタスクを行うために多くの方法を追加すると、オブジェクトを使用する上での柔軟性が高くなります。例えば、noteout が1つのインレットしか持たず、音を演奏するたびに必ず3つの数から成るリストを要求するとしたら、Maxは非常に使い勝手が悪いでしょう。逆に、3つの数から成るリストを送信すると音が演奏できるということによって、より容易に目的を達成することができる場合もあるかもしれません。

メッセージをバインドする(関連づける)ためのルーチン

これらのルーチンは初期化ルーチンの中で用いられるもので、setup を呼び出した後で、メッセージをクラスの中に書かれた関数(これをメソッドと呼びます)にバインド(関連づけ)します。最も一般的に用いられるメッセージのための単純化されたルーチンがある一方で、どのようなメッセージでもバインドすることができる addmess もあります。

addbang

 
  通常のトリガメッセージであるbangに関数をバインドするために使われます。
 
  void addbang (method mp);
 
  mp bang メソッドとなる関数

addfloat

 
  addfloat は左端のインレットで受信した float メッセージに関数をバインドするために使います。
 
  void addfloat (method mp);
 
  mp floatメソッドとなる関数

addftx

 
  addftxは左端のインレット以外で受信したfloatメッセージに関数をバインドするために使います。
 
  void addftx (method mp; short inlet);
 
  mp floatメソッドとなる関数
  inlet このメソッドで結び付けるインレットの数。1は左端のインレットの右隣のインレットを表します。

addint

 
  addintは左端のインレットで受信したintメッセージに関数をバインドするために使います。
 
  void addint (method mp);
 
  mp intメソッドとなる関数

addinx

 
  addfinxは左端のインレット以外で受信したintメッセージに関数をバインドするために使います。
 
  void addinx (method mp; short inlet);
 
  mp intメソッドとなる関数
  inlet このメソッドで結び付けるインレットのナンバー。1は左端のインレットの右隣のインレットを表します。

注:インレットの場所とメッセージの一致は自動的には行われませんが、従来の習慣に従うことを強く推奨します。あなたのクラスのオブジェクトを作成する際には、intin floatin をインスタンス生成関数で的確に使用することによって、データの受け渡しを設定すべきです。(Chapter 6を参照)

addmess

 
  addmessは上記のような標準のメッセージ以外のメッセージをバインドする際に使用します。
 
  void addmess (method mp, char *sym, short types...);
 
  mp メソッドとなる関数。
  sym メッセージを定義するCの文字列。
  types メッセージへのアーギュメントを指定する1つ以上の整数。標準のMaxのlist型フォーマット。 (Chapter 3を参照)。
  addmess 関数は、mp をポインタとする関数を追加します。この関数は、オブジェクトの左端のインレットへの sym メッセージ文字列に応答します。メッセージのアーギュメントの型チェックはアーギュメントの型を指定したリストを渡すことで行われます。リストの最後は0(A_NOTHING)でなければなりません。型チェックが行われるアーギュメントの数は最大7個です。

標準メッセージセレクタ

このセクションでは、Maxオブジェクトが送受信する int、bang、float 以外の標準的なメッセージについて述べます。

Anything

     
  他のメソッドで扱わなかった、あらゆるメッセージに対応するメソッドが必要な場合、addmess を使って anythingという名前の関数にバインドすることができます。
     
バインディング
     
  addmess (myObject_anything, "anything", A_GIMME, 0);
     
宣言
 
     
  myobject_anything (myObject *x, t_symbol *message,short argc, t_atom *argv)
     
  message 受信したメッセージの名前
  argc argv配列のアーギュメントの数(Atoms)
  argv メッセージアーギュメントの配列
     
  例えば、次のパッチで、prepend オブジェクトは cheese 4 5 6 というメッセージを受け取ります。このオブジェクトの anything メソッドでは、argc は3で、argv には4,5,6という数値を持った t_atomが含まれます。message はシンボル(t_atom ではありません)cheese になります。

list

     
  このメッセージは、オブジェクトに送られるメッセージが数値で始まる場合に、オブジェクトに対して送られます。リストは 2個以上のint、float、または、t_symbolの配列になります。最初の数値は常にintまたはfloatです。
     
バインディング
     
  addmess (myObject_list, "list", A_GIMME, 0);
     
宣言
 
     
  myobject_list (myObject *x, t_symbol *msg, short argc,t_atom *argv)
     
  msg 受信したメッセージの名前
  argc argv 配列の値 (t_atoms) の数
  argv listを含むt_atomsの配列
     
  リストは A_LONGA_FLOAT、さらにA_SYM 型の t_atomを含んでいる可能性がありますが、リストの最初のエレメント(要素)は決してt_symbol にはなりません。t_symbolを示す引数 msg は重要ではなく、無視されます。下の図で、ユーザがメッセージボックスをクリックすると prepend オブジェクトの list メソッドが呼び出され、argv は(順に)7,8,9という数値の t_atom を持ちます。

他の標準メッセージ

ある特定の語をメッセージとして使用するように設計する場合には、既存のMaxオブジェクトですでに使用されている語を使うようにしてみて下さい。それには、このようなものがあります 。

set N 出力せずに値をセット。
start 何かを始める、またはbangかゼロ以外の値を使う。
stop 何かを止める、またはゼロを使う。
record  
append  
read S ファイルを読む。 (importも使用できる), S はオプションのファイル名。
write S ファイルに書き込む。(exportも使用できる), S はオプションのファイル名。
next 次の値を出力、次に進む。
prev 前の値を出力、前に戻る。
goto N Nをカウンタとして、nextまたはprevをセット。
size N サイズをNにセット。
zero すべてをゼロにセット。
clear 削除、消去、ゼロにセット。場合によっては、指定したアーギュメントをクリアし、アーギュメントが指定されない場合はすべてをクリア(またはゼロにする) 。
length 長さを出力。

Maxからのメッセージ

実装することのできる定義済みのメッセージがいくつかあります。

enable および disable

     
  これらのメッセージはユーザが pcontrol を使って、MIDIの使用を可能(enable)、または不可(disable)にする場合に送られます。(以前、MaxのMacOS9上のバージョンではパッチャーウィンドウのタイトルバーにあるMIDIアイコンのクリックによってこの動作を行っていましたが、このアイコンは現在では無くなっています)
     
バインディング
     
  addmess (myObject_enable, "enable", 0);
     
宣言
   
  myobject_enable (myObject *x);myobject_disable (myObject *x);
   
  パッチャーでMIDIを使用不可にすると、そのパッチャーウィンドウ内のすべてのオブジェクトに disable メッセージが送られます。既存のMaxオブジェクトでは、MIDIオブジェクト(noteinnoteout など)だけが、このメッセージに応答します。しかし、あなたのオブジェクトがMIDIに似たような方法で外部と直接コミュニケートしている場合、disable メッセージに対応してコミュニケーションを使用停止にしたり、enable メッセージによって再開したりしようと思うかもしれません。この場合、初期値としての enable メッセージを受け取ることはないため、常にオブジェクトがイネーブル状態で生成されるようにして下さい。

info

     
  infoメッセージは、ロックされていないパッチャーウィンドウでユーザがオブジェクトを選択してMaxメニューの Get info... を選んだ場合に、オブジェクトに送られます。
     
バインディング
     
  addmess (myObject_info, "info", A_CANT, 0);
     
宣言
   
  myobject_info (myObject *x, t_patcher *parent,t_box *container)
     
  parent オブジェクトを含むパッチャー。
  container オブジェクトを含むBox(Boxについてのより詳しい情報はChapter 11 を参照)
     
 

このとき、オブジェクトのパラメータをセットしたり、表示したりするためにダイアログボックスを開きます。また、この機会を利用して、Maxのエクスターナルオブジェクトを書くことができることのすばらしさをAboutボックスを表示して誇示することもできます。さらに、infoメッセージはインスペクタパッチを表示するために使用することもできます。(Chapter 11 に説明があります)

t_patchert_box の定義は ext_user.h というヘッダファイルにあります。パッチャーやボックスに対して、このメソッドでアクセスする必要はあまりないかもしれません。その場合、あなたのinfoメソッドを次のように宣言することができます。
     
  void myobject_info (myObject *x, void *p, void *b);

preset

     
  このメッセージは、preset オブジェクトによって送られ、あなたのオブジェクトの現在のステート(状態)の提供を要求します。
     
バインディング
     
  addmess (myObject_preset, "preset", A_CANT, 0);
     
宣言
   
  void myobject_preset (myObject *x);
     
 

preset メッセージに応答して、オブジェクトを現在の状態にリストア(復元)するためのメッセージを供給します。これは、set または intメッセージ、あるいは、オブジェクトが多くの変更可能なデータを持っている場合は、より複雑なメッセージによって行われます。これにより、あなたのオブジェクトに対しMaxにビルトインされているpresetオブジェクトが適用できます。

preset_intpreset_setpreset_storeなどの関数は preset メソッドを書く際、役に立ちます。Chapter 9のPreset に関するセクションでは、これらのルーチンについて述べていますので参照して下さい。

loadbang

     
  パッチャーウィンドウがファイルからロードされた際に、これを含む各々のオブジェクトはloadbangメッセージを受信することができます。
     
バインディング
     
  addmess (myObject_loadbang, "loadbang", A_CANT, 0);
     
宣言
   
  void myobject_loadbang (myObject *x);
     
 

パッチャーウィンドウがロードされた時にbangを送る、loadbangと呼ばれるMaxのビルトイン(組み込み)オブジェクトがあります。必要ならば、オブジェクトはloadbangメッセージに何かの方法で応答することができます。loadbang に応答するメソッドが実装されていない場合でも、ユーザは必要に応じて初期化を行うためにオブジェクトを loadbang オブジェクトのアウトレットと接続することができるということは心にとめておいて下さい。オブジェクトを含むMaxファイルがディスクからロードされる時点でだけ loadbang メッセージを得ることができ、ユーザがパッチャーウィンドウで新しいインスタンスを作った時点では loadbang メッセージは得られないという点に注意して下さい。


assist

     
  このメッセージは、ユーザがオブジェクトのインレット、またはアウトレットの1つの上にカーソルを持ってきた時、パッチャーウィンドウのアシスタンスエリアが可視である場合にオブジェクトに対して送られます。
     
バインディング
     
  addmess (myObject_assist, "assist", A_CANT, 0);
     
宣言
   
  void myobject_assist (myObject *x, void *box, long msg, long arg, char *dstString);
     
  box あなたのオブジェクトを含むボックス(ボックスについての詳細はChapter 11を見て下さい。)このアーギュメントはassistメッセージに対する応答としてはほとんど利用されることはありません。
  msg ASSIST_INLET(1)またはASSIST_INLET(2)の2つの値のうちのどちらかが、インレットまたはアウトレットについて解説しているかどうかに関わりなく表示されます。
  arg インレット、またはアウトレットのナンバ。左端のインレット、またはアウトレットを基準にして0から始まります。
  dstString ここへ、該当のインレット、またはアウトレットについてのアシスタンス情報の C文字列をコピーしなければなりません。
     
 

assistメッセージに応答するためには、60文字以内でインレット、またはアウトレットの機能をユーザに説明しなければなりません。既存のMaxオブジェクトのアシスタンスメッセージの例を見て下さい。特定のアーギュメントやインスタンスの状態に適用できる感じを抱くかも知れませんが、オブジェクトの内部状態が変更されても、新しいassistメッセージは送信されません。

このメッセージに対しての応答に関する全ての動作は assist_string 関数を、国際化の可能な STR#リソースに関連づけて使うことで行うことができますが、クロスプラットフォーム環境での互換性を高めるために、下記のような旧来の方法で行うことを推奨します。

void myobject_assist (myObject *x, void *b, long msg, long arg, char *dst) { if (msg==ASSIST_INLET) { switch (arg) { case 0: strcpy(dst,"Start Clock Ticking"); break; case 1: strcpy(dst,"Set Clock Speed in Milliseconds"); break; case 2: strcpy(dst,"Set Clock Erratic Factor (0-99)"); break; } } else if (msg==ASSIST_OUTLET) { strcpy(dst,"Clock Ticks"); } }

save

     
  saveメソッドを含むことによって、オブジェクト(ユーザインターフェイスオブジェクトでないもの)の内部状態を、ユーザがオブジェクトボックスに入力する以上に保存することができます。
     
バインディング
     
  addmess (myObject_save, "save", A_CANT, 0);
     
宣言
   
  void myobject_save (myObject *x, Binbuf *dest);
     
  dest オブジェクトの状態をファイルからリストアするために作成したメッセージの転送先 。
     
 

このメソッドの実装についてのより詳しい内容は、Chapter 7 の binbuff_vinsert の説明の中で述べられています。本質的な考え方は、現在のパラメータであなたのオブジェクトを再現する new オブジェクトに送ることができるようにメッセージをフォーマットし、関数によってこのメッセージを相手のデータバッファである dest にコピーするというものです。いくつかのsaveメソッド(例えば、coll オブジェクトが現在のデータを保存するために用いられるもの)は、より精巧です。これは、内部状態をリストアされるオブジェクトの新しく作られたインスタンスに対して送るメッセージを含むことができます。

注:あなたのオブジェクトがsaveメソッドを実装する場合、ユーザが内部状態を変更した後に保存されていないデータが存在するときにはそのパッチャーウィンドウをマークしておく必要があるかもしれません。これを行うための情報は、Capter 11の patcher_dirty ルーチンの説明を参照して下さい。