Max/MSP でのプログラミングで,
軽いつもりのパッチが不思議に重くなっていて, しらべてみたら同じパッチが何枚も立ち上がっていた, なんてことがよくあります.
オブジェクト指向言語では, 同時に存在するインスタンスをつねにひとつに制限する「シングルトン」というプログラムの書き方があるのですが, Max でもこれができないかと思い, 試してみることにしました.
以下が完成したパッチです.
パッチの要点
作成にあたり, 方針を以下のように定めました.
- 肝となるインスタンス ( =パッチ) 数の管理に [value] オブジェクトを使う
- パッチ起動時にガードをかけるのが理想. しかし手だてがない.
そこで, 「同じパッチを立ち上げるとすぐパッチを閉じる」という方針とした. - なるべく基本的なオブジェクトを使って作成する.
処理のながれ
実際に処理の流れを追いかけて, どのようにシングルトンが実現されているのかを説明します.
- 凡例 -
-
[foobar]
foobar というオブジェクトをあらわします -
"tomtom"
tomtom というメッセージをあらわします
1つめのパッチの起動 〜 [value] に 1 が格納される
- [value] の, 「未初期化状態では "bang" に反応しない」という性質を利用しています.
- [if] は "1 == 0" を評価して偽 ( "0" をアウトレット1から出力 ) を送信します.
- この結果、[value] に "1" が送信され, [value] に 1 が格納されます.
2つめのパッチの起動 〜 パッチクローズする
- [value] には, 1 が格納されているため, [loadbang] により [value] が "1" を送信します.
- [if] は "1 == 1" を評価して真 ( "1" をアウトレット1から出力 ) する.
- [thispatcher] に "wclose" が送信され, 当該パッチが閉じる.
- [onebang] は, 1つめのパッチで [value] の値の更新を1度きりと制限するために入れています.
サンプルパッチ
以下のコード片をテキスト形式で保存して, Max で開くことができます.
singleton.maxpat
{
"patcher" : {
"fileversion" : 1,
"appversion" : {
"major" : 6,
"minor" : 0,
"revision" : 0
}
,
"rect" : [ 149.0, 93.0, 331.0, 353.0 ],
"bglocked" : 0,
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 0,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 0,
"statusbarvisible" : 2,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"description" : "",
"digest" : "",
"tags" : "",
"boxes" : [ {
"box" : {
"fontname" : "Hiragino Maru Gothic Pro W4",
"fontsize" : 12.0,
"id" : "obj-4",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 9.0, 22.0, 142.0, 24.0 ],
"presentation_rect" : [ 23.0, 38.0, 0.0, 0.0 ],
"text" : "二重起動を防止する"
}
}
, {
"box" : {
"fontname" : "Hiragino Maru Gothic Pro W4",
"fontsize" : 12.0,
"id" : "obj-1",
"maxclass" : "comment",
"numinlets" : 1,
"numoutlets" : 0,
"patching_rect" : [ 9.0, 5.0, 143.0, 24.0 ],
"text" : "singleton patch in Max"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-46",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 110.0, 201.0, 145.0, 20.0 ],
"text" : "if $i1 == $i2 then 1 else 0"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-44",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 110.0, 175.0, 56.0, 20.0 ],
"text" : "pack 1 0"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-35",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "bang", "bang" ],
"patching_rect" : [ 110.0, 110.0, 34.0, 20.0 ],
"text" : "t b b"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-29",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 2,
"outlettype" : [ "", "" ],
"patching_rect" : [ 137.5, 310.0, 69.0, 20.0 ],
"save" : [ "#N", "thispatcher", ";", "#Q", "end", ";" ],
"text" : "thispatcher"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-27",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 137.5, 286.0, 47.0, 18.0 ],
"text" : "wclose"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-24",
"maxclass" : "message",
"numinlets" : 2,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 110.0, 257.0, 37.0, 18.0 ],
"text" : "set 1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-23",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "" ],
"patching_rect" : [ 147.0, 145.0, 61.0, 20.0 ],
"text" : "v _static_"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-22",
"maxclass" : "newobj",
"numinlets" : 1,
"numoutlets" : 1,
"outlettype" : [ "bang" ],
"patching_rect" : [ 110.0, 57.0, 60.0, 20.0 ],
"text" : "loadbang"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-21",
"maxclass" : "newobj",
"numinlets" : 2,
"numoutlets" : 2,
"outlettype" : [ "bang", "bang" ],
"patching_rect" : [ 110.0, 84.0, 67.0, 20.0 ],
"text" : "onebang 1"
}
}
, {
"box" : {
"fontname" : "Arial",
"fontsize" : 12.0,
"id" : "obj-20",
"maxclass" : "newobj",
"numinlets" : 3,
"numoutlets" : 3,
"outlettype" : [ "bang", "bang", "" ],
"patching_rect" : [ 110.0, 227.0, 74.0, 20.0 ],
"text" : "select 0 1"
}
}
],
"lines" : [ {
"patchline" : {
"destination" : [ "obj-24", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-20", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-27", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-20", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-35", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-21", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-21", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-22", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-44", 1 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-23", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-23", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-24", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-29", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-27", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-23", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-35", 1 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-44", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-35", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-46", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-44", 0 ]
}
}
, {
"patchline" : {
"destination" : [ "obj-20", 0 ],
"disabled" : 0,
"hidden" : 0,
"source" : [ "obj-46", 0 ]
}
}
],
"dependency_cache" : [ ]
}
}