Jitterでは、マトリックスは名前による参照として Maxオブジェクト間でやり取りされます。この名前による参照は、Jitter が jit_object_register() 関数を使って、対応する名前でこれらのマトリックスを登録することによって作成されます。オブジェクトの登録が役に立つのには、いくつかの理由があります。まず第1は、登録されたマトリックスは jit_object_findregstered() 関数を使って、名前によって参照することができます。第2に、登録されたオブジェクトは、jit_object_attatch() を使ってこれに接続されたクライアントに対して通知イベントを送信することができます。最後に、特定の状況では、オブジェクトの登録処理を使って、jit.matrix の場合のように、オブジェクトの1つのインスタンスへの複数の外部参照を持たせることができます。
オブジェクトの登録は、jit_object_register() 関数を使って行なうことができます。この関数は gensym("jitter") によって 関連付けられるネームスペースの中では、Max の object_register() 関数と同等のものです。object_register() 関数に関するより詳しい情報は、Pattr SDK を参照して下さい。そこでは、この関数の他 Max の新しい "obex" オブジェクトモデルについても述べられています。 Jitter では従来から jit_object_register() をオブジェクトの "register" メソッドにバインドし、このメソッドを呼び出すために jit_object_method() を使用しています。次は、SDK の jit.notify からの例です。
// Jitter オブジェクトの割り当てを行ないます。 if (o=jit_object_new(gensym("jit_notify"))) { ... // ユニークな名前を生成します。 x->servername = jit_symbol_unique(); // 与えられた名前でオブジェクトを登録します。 jit_object_method(o,_jit_sym_register,x->servername); ... }
個別な名前を使用しない場合、上記の例のように jit_symbol_uniqhe() 関数を使って、ユニークな名前を生成する方法も良いでしょう。この名前は、登録されたオブジェクトが開放されると、再利用の候補となります。これによって、ユニークな名前を関連付けるシンボルテーブルによって過剰なメモリが使用されることを防止できます。jit.matrix オブジェクトで通常用いられるように、オブジェクトが1つのインスタンスに対していくつかの名前による多重参照を行なえるようにしたい場合には、任意のインスタンスで jit_object_register() の戻り値を使い、そのオブジェクトポインタを登録処理の後で保存しておくことが重要です。同じクラスによってすでに登録されているオブジェクトが存在する場合、登録されようとしているオブジェクトは開放され、同じクラスの既に登録済みのオブジェクトが返され、参照の数が増えます。この種の処理の実装を他の状況で行なう必要があるかもしれませんが、これは、通常、 jit.matrix オブジェクトの登録処理の範囲内の問題です。Jitter の中でオブジェクト登録が使用されるその他のほとんどの場合では、1つのインスタンスを登録することが、求められ、許可されます。上記の例では、このような処理が安全であることがわかっているため、 jit_symbol_unique() を使ってユニークな名前を生成しています。名前をつけられたオブジェクトは、jit_object_unregister() 関数によって登録を解除することもできますが、通常、これはオブジェクトが開放される場合、あるいは、オブジェクトが違う名前で再登録される場合に行なわれます。このようなコンテキストの中以外では、Jitter コードの中でこのような処理が使用されることはあまりありません。
登録済みのオブジェクトは、jit_object_findregistered() 関数を使って名前で検索することができます。例えば、この関数を使って名前付きのマトリックスを特定することができます。ほとんどのマトリックスオペレータオブジェクトは、デフォルトの MOP コードによってこれを行ないますが、しかし、例えば、SDK の jit.pack の例のように、独自の jit_matrix メソッドを持つ MOP では、jit_matrix メソッドの中で jit_object_findregistered() を利用しています。
// 提供された atom 引数から私たちのマトリックス名を取得します。 matrixname = jit_atom_getsym(argv); // 名前に基づいて検索します。 matrix = jit_object_findregistered(matrixname); // 有効なポインタであることを確認し、 "class_jit_matrix" メソッドが存在すれば 1 を // を返します。 if (matrix&&jit_object_method(matrix, _jit_sym_class_jit_matrix)) { ... }
オブジェクトが登録されると、これをサーバと考えることができるようになり、このオブジェクトに対して接続を行なったクライアントに様々なイベントを通知することができるようになります。名前を付けられたオブジェクトに接続するには、jit_object_attach() 関数を使用します。同様に、名前を付けられたオブジェクトから接続を解除するためには、 jit_object_detatch() 関数を使用します。オブジェクトのデストラクタの中でサーバとの接続を解除したり、任意のタイミングでオブジェクトが接続されたサーバを変更することが一般的です。クライアントオブジェクトがサーバオブジェクトからすべての通知を受け取るためには、オブジェクトに "notify" メソッドを定義し、これによって接続したすべてのオブジェクトからの通知を受け取ることが重要です。SDK サンプル jit.notify の Max ラッパーオブジェクトで定義された "notify" メソッドの例を次に示します。ここでは、内部的な Jitter オブジェクトのインスタンスからいくつかの atom の値を受信しています。このオブジェクトはマトリックスオペレータであるため、次の例の中で jit.notify が max_jit_classex_mop_wrap() 関数 を MAX_JIT_MOP_FLAGS_OWN_NOTIFY フラグと共に呼び出してデフォルトで MOP が持つ notify メソッドをオーバーライドしている点、また、他のすべてのメッセージを標準の max_jit_mop_notify メソッドに渡すことによって、入力マトリックスと出力マトリックスに対するすべての変更がデフォルトの MOP コードに通知されるようになっている点は重要です。
// s はサーバ名、msg はメッセージ、ob はサーバオブジェクトへのポインタ // data は与えられたメッセージのためにサーバが受け取ったかもしれない追加のデータ void max_jit_notify_notify(t_max_jit_notify *x, t_symbol *s, t_symbol *msg, void *ob, void *data) { if (msg==gensym("splat")) { post( "notify: server=%s message=%s ",s->s_name,msg->s_name); if (!data) { error( "splat message NULL pointer "); return; } // ここで右端のアウトレットを使って出力を行ないます。 // ここでは、たまたま"data " が t_atom[3] を指すことがわかっています。 // あるいは、max_jit_obex_dumpout_get を使ってアウトレットへのポインタを // 取得することもできます。 max_jit_obex_dumpout(x,msg,3,(t_atom *)data); } else { // これはMOPであるため、それぞれのインプット、アウトプットにすべてのマトリックス // を接続します。そして、デフォルトのMOPのnotifyメソッドを呼び出してこれを扱う // 必要があります。 // (これは、MOP がマトリックスの新しい名前の取得、開放、変更の処理を行なう方法 // です。) max_jit_mop_notify(x,s,msg); } }
登録しようとするオブジェクトの作成を行なう場合、アトリビュートが変更された場合にすべてのクライアントに送られるアトリビュートのデフォルトの通知に加え、独自の通知を送信したり、デフォルトのオブジェクト開放通知を送信したい場合、jit_object_notify 関数を使用する必要があります。この関数によって、すべてのクライアントに対して通知を行なう場合に用いるメッセージ名の変更や、オプションとして追加する、タイプされていないデータを指定することができます。クライアントに送信する追加のデータを選ぶ場合、すべてのクライアントコードで、この情報をどのようにアンパックすればよいかを知っておく必要があります。次の、 SDK サンプル jit.notify からの例では、Max のラッパーオブジェクトに対して何らかのデータを送信する notify メカニズムを使用しています。
t_atom foo[3]; jit_atom_setlong(&foo[0],1); jit_atom_setlong(&foo[1],2); jit_atom_setlong(&foo[2],3); jit_object_notify(x,gensym("splat"),foo);