チュートリアル 16:
メッセージのリモート送信

イントロダクション

これまでのチュートリアルでは、オブジェクトとオブジェクトの間のメッセージはすべてパッチコードを使って送信されていました。しかし、オブジェクト間でメッセージを送信するもう1つの方法があります。これは、Max に組み込まれているメッセージのリモート送信メカニズムを利用するものです。そのために用意されたオブジェクトがあります(そのままの名前ですが、send と receive というオブジェクトです)。また、メッセージボックスの内容をオブジェクトに送信するという方法もあります。チュートリアルの最後では、変数を格納することができ、複雑なパッチの中での値の移動を行ないやすくするオブジェクトを使います。

パッチがだんだん複雑になるにしたがって、パッチのモジュール化やコンパートメント化を行なう様々なテクニックを使用する必要性が高まります。このようなテクニックを使うと、パッチがより解りやすくなり、パッチのメンテナンスや拡張が容易になります。パッチの中に数多くのロジックがある場合、パッチコードを維持しようとすると、必要以上に見た目が複雑になってしまうことがあります。パッチコードを使用しないメッセージの受け渡しを可能にするツールを使うと、パッチの動作に影響を与えずにパッチを整頓することができます。

send とreceive による処理

チュートリアルを開いて下さい。

パッチコードを使わずにメッセージを送信する最も一般的な方法は、send オブジェクトとreceive オブジェクトを使ってメッセージの受け渡しを行なうというものです。チュートリアルパッチを見ると、パッチの左上の部分でsend オブジェクトとreceive オブジェクトが整数値の受け渡しを行なっていることがわかります。上側のナンバーボックスの値を変更すると、整数の値が send fred オブジェクトに渡されます。この値は、Max 環境の中で「ブロードキャスト(放送)」され、fred という同じ名前を持つすべての receive オブジェクトがこれを受信します。ここでは、すぐ下にある receive fred オブジェクトがメッセージを受信し、接続されているナンバーボックスにこの値を出力して表示させています。

メッセージは名前を使ってブロードキャスト(放送)されるため、send オブジェクトと同じ名前を持ったreceive オブジェクトであれば、このメッセージを受信できます。したがって、メッセージの受信を行なう複数のreceive オブジェクトを作ったり、同じ名前を使ってメッセージを送信する複数のsend オブジェクトを作ることができます。このテストパッチでは、sliderを send bob オブジェクトに接続して、これを行なっています。ここでは、値(slider または ナンバーボックスによってセットされます)を、bob という名前を持ったすべての receive オブジェクトに送信しています。パッチの右下には2つの receive bob オブジェクトがあります。1つはslider にに接続され、もう1つは直接ナンバーボックスに接続されています。上の slider の値を変更すると、2つの receive オブジェクトの値が同時に変わります。

send と receive オブジェクトのペアを使う場合、送信されたメッセージはMax環境の中のすべてのreceiveオブジェクトで受信されるということを認識しておくことが重要です。これは、別のパッチにあるreceive オブジェクトの場合でもあてはまります。このことをテストするために、新しいパッチを(File メニューから New Patcher を選んで)開いて下さい。新しいオブジェクトを作り、receive bob と入力して下さい。receive オブジェクトの出力をナンバーボックスに接続し、チュートリアルパッチに戻って下さい。メインパッチのslider の値を変更すると、sendの出力が、メインパッチの receive bobオブジェクトだけでなく、新しいパッチに作った receive オブジェクトでも受信されることがわかるでしょう。

他の人が作ったパッチを使ったときに、"s" や "r" というオブジェクトを見たことがあるかもしれません。send や receive オブジェクトはとても頻繁に使われるため、send と receive には、それぞれ "s" と "r" というエイリアス(ショートカット)名があります。このショートカット名を使うと、入力が楽になるだけでなく、オブジェクトのサイズも小さくて済みます!

forward の使用

メッセージのリモート送信に使用される、もう1つの一般的な方法は、メッセージボックスの内容を1つ、あるいは複数のreceive オブジェクトに送信するというものです。そのためには、メッセージの最初にセミコロン(;)とreceive オブジェクトの名前を入力する必要があります。;bob 155 というメッセージでは、bob という名前を持つすべての receive オブジェクトに値 155 を送信します。

パッチの左下にある大きなメッセージボックスは、直接メッセージを送信している例です。ここでは4つのメッセージが作られます。そのうちの2つは lcd1 という送信先へ、2つは lcd2 という送信先へ送られます。メッセージボックスをクリックすると、2つの lcd オブジェクトはそれぞれに接続されているreceiveオブジェクトから、それぞれ適切な描画コマンドを受信します。上の lcd(lcd1)は青い円を描き、下の lcd(lcd2)は緑の矩形を描きます。

一般的に、メッセージを何らかの論理的な判定基準によって、1つ、あるいは複数の送信先へ送ることも必要になります。これは、切り替えを行なうロジック(例えば、gate オブジェクトを複数のsend オブジェクトに接続する方法)を使うことで可能になります。しかし、送信先を選んでメッセージを送るために、foward オブジェクトを使うこともできます。上で述べたメッセージボックスの例は、forward オブジェクトがサポートする機能と同じものです。

どのような名前を持った送信先でメッセージを受信するかを選ぶことができます。forward オブジェクトに send メッセージを送ると、入力されるメッセージの送り先の名前を設定できます。送り先を設定すると、入力したメッセージはその送り先に適切に送信されます。send lc1 というメッセージボックスをクリックすると、ナンバーボックスの値を変更したときに第1の lcd オブジェクトに色付きの矩形が描画されます。send lcd2 というメッセージボックスをクリックすると、forward オブジェクトの出力先は receive lcd2 オブジェクトに切り替わります。今度は、ナンバーボックスを変更すると、第2の lcd オブジェクトに矩形が描画されます。

これと同様に、アーギュメントを持たない receive オブジェクトは任意の名前の send、あるいは適切に設定された forward や メッセージボックスからメッセージを受信するために使うことができます。receive オブジェクトにset メッセージを送ると、いわば「名前の変更」を行なうことができます。このため、パッチの中の異なった場所からメッセージを受信することができます。forward オブジェクトの隣には、このような receive オブジェクトがあります。bob と fred という2つの送信先を(メッセージボックスを使って)切り替え、この名前を使って送信を行なうナンバーボックスや slider オブジェクトを操作すると、これがどのように動作するかを見ることができます。receive に存在しない名前(例えば none)を設定すると、パッチの中のどの送信先からも切り離されます。receive オブジェクトを「切り替え可能」にするためには、アーギュメントを指定せずにオブジェクトを作成する必要がある点に注して下さい(アーギュメントを指定した場合、インレットは作られません)。

int、float、value オブジェクト

パッチプログラミングを行なっていると、必要があるまで値を「格納」しておく場所が不可欠になることがあります。整数ナンバーボックスと浮動小数点ナンバーボックスを使うことはできますが、これらのオブジェクトは、UI によってユーザに変更されてしまう可能性があります。シンプルな変数の格納場所を提供し、その内容を呼び戻すために、こういった目的での使用にに特化した一組のオブジェクトがあります。intオブジェクト と float オブジェクトは、値の一時的な格納場所としての動作を行なうことができます。左インレットにやってきた数値は格納され、直ちに送信されます。これに対し、右インレットにやってきた数値は格納されますが、送信は行なわれません。int オブジェクトや float オブジェクトに格納してある値を取り出したい場合には、左インレットにbang メッセージを送信する必要があります(例えば button オブジェクトなどから送信します)。int オブジェクトや float オブジェクトが優れている点の1つは、他のメッセージを使用せずに初期化することができることです。オブジェクトに与えられるアーギュメントは初期値になります。これらを設定するためにloadbang メッセージや他の機能を使用する必要はありません。パッチの右側にある int オブジェクトと float オブジェクトを見ると、その動作を理解することができます。button オブジェクトでbang を送信すると、初期値を出力します。ナンバーボックスから値を入力し始めると、この新しい値は再び bang が送信されるまでオブジェクトの内部に格納されます。このパッチには、int や float オブジェクトの下に、value というオブジェクトが2個あります。value オブジェクトは int/float オブジェクトと send/receiveのペアをを組み合わせたようなオブジェクトです。それぞれの value オブジェクトは名前(この場合は joe)を持っていて、value オブジェクトのどれか1つに値が格納されると、その値は同じ名前を持つ他のvalue オブジェクトすべてで共有されます。注意すべき点の1つは、value オブジェクトにメッセージを送信しても、出力をトリガしないということです。そのため、value オブジェクトにbang メッセージを送信して、明示的に出力させる必要があります。テストパッチで、1つのオブジェクトの値を変更し、他のオブジェクトに bang を送信して下さい。値が魔法のように1つのオブジェクトから他のオブジェクトへ転送されることがわかります。int や float オブジェクトと異なり、value はあらゆるタイプのメッセージを扱うことができます。シンボル、整数、浮動小数点数はすべて value オブジェクトに格納することができます。リストも同様に格納できます。これは便利ですが、同時に、出力を表示させるために valueオブジェクトに接続するオブジェクトには注意を払う必要があるということを意味しています。テストパッチでは、value オブジェクトにナンバーボックスが接続されています。しかし、実際には、value オブジェクトは様々なタイプの値を受け取ることができるため、print オブジェクトや、他の表示用オブジェクトを接続したほうがよいでしょう。

結び

パッチコードの接続なしにメッセージを送信できることによって、パッチの中の配置をより柔軟に行なう可能性を与えてくれます。そして、パッチ全体を通して非常に複雑なメッセージを作り、送信することを可能にしてくれます。sendオブジェクト と receive オブジェクトの使用は、パッチコードを使用せずにパッチ内でメッセージを渡す最も一般的な方法です。メッセージボックスの表記法やforward オブジェクトを使ったルーティングは、パッチの見た目の複雑さを最小限に抑えるための手助けとなります。最後に、int や float オブジェクトに値を格納する方法、value オブジェクトによって送られてきたデータの格納と送信を行なう方法について見ました。

参照

send パッチコードを使わずにメッセージを送信します。
receive パッチコードを使わずにメッセージを受信します。
forward 様々なオブジェクトにメッセージをリモート送信します。
int 整数を格納します。
float 浮動小数点数を格納します。
value 格納された値を複数のオブジェクトで共有します。