ChucK(miniAudicle)のMAUI

ChucKGUIScreenCapture01


on the flyのlivecodingが基本のChucKなんだけど。
macのmidiAuidcleだけ?)簡易的なUser Interface Elements APIが使えます。


現状(mac版の0.1.3.9 (alpha))だと

MAUI_View ウインドウ
MAUI_Gauge プログレスバー
MAUI_LED LED
MAUI_Button ボタン(プッシュ/トグル)
MAUI_Slider スライダー

が使えます。
せめて単なるラベルが欲しかったけど。。。贅沢は言えん。


ボタンやらスライダーのインスタンスをつくってMAUI_ViewにaddElementするだけです。

MAUI_View control_view;
MAUI_Button screenSelect[8];
MAUI_Button trackSelect[4];
MAUI_Slider bpmChange;
string buttonLabel[8];

//ウインドウの初期化
control_view.size(430, 300);
control_view.name("Beat Slicer::Monome");

//スライダー
"BPM" => bpmChange.name;
bpmChange.display();
bpmChange.irange(20, 200);

bpmChange.range(20, 200);
bpmChange.size(420, bpmChange.height());
bpmChange.position(10, 0);
bpmChange.value(bpm);
bpmChange.name("BPM");
control_view.addElement(bpmChange);

80 => int y;
0 => int pos;

//トグルボタン・グループ1
for (0 => int i; i < 4; i++) {
	trackSelect[i].toggleType();
	trackSelect[i].size(125, 75);
	trackSelect[i].position(pos, y);
	trackSelect[i].name("Track "+(i+1));
	control_view.addElement(trackSelect[i]);
	
	100 +=> pos;
}

160 => y;
0 => pos;

//ボタンのラベル*8
"Sample"  => buttonLabel[0];
"Gain"    => buttonLabel[1];
"Attack"  => buttonLabel[2];
"Release" => buttonLabel[3];
"Pitch"   => buttonLabel[4];
"Pan"     => buttonLabel[5];
"Reverce" => buttonLabel[6];
"Repeat"  => buttonLabel[7];

//トグルボタン・グループ2
for (0 => int i; i < 8; i++) {
	screenSelect[i].toggleType();
	screenSelect[i].size(125, 75);
	screenSelect[i].position(pos, y);
	screenSelect[i].name(buttonLabel[i]);
	control_view.addElement(screenSelect[i]);
	
	if (i == 3) {
		50 +=> y;
		0 => pos;
	}
	else 100 +=> pos;
}

//表示
control_view.display();


で、実行するとこんな感じです。

ChucKGUIScreenCapture02


こいつら全てEventクラスを継承してるので、ボタンが押された時の処理とかはイベントリスナでonChangeなEventを拾ってごにょごにょします。イベントリスナは明示的に別プロセス(ChucKではshredとか言う)で走らせます。
ちなみに、ChucKはプロセスの同期/非同期とタイミング合わせが簡単にできるように用意されていて、Strongly-timedだと言うだけはあるなぁ、と。


で、リスナはこんな感じです。

//イベントリスナのプロセス登録
spork ~changeBPMListener();

//リスナ関数
function void changeBPMListener() {
	while(true) {
		//何か処理
	}
}


排他的なトグルボタン・グループみたいなやつの場合。

//ボタンの数だけリスナのプロセスを登録しとく
for(0 => int i; i < 4; i++) spork ~ trackSelectListener(i);

//リスナ関数
function void trackSelectListener(int index) {
	while (true) {
		trackSelect[index] => now;//ボタンが押されるのを待ってる
		
		//他のボタンをオフする
		for(0 => int i; i < 4; i++) {
			if(i != index){
				trackSelect[i].state(0);
			}
		}
		
		//ここで再度明示的にオンにしないとうまく動作しない場合があったので一応
		trackSelect[index].state(1);
		
		trackSelect[index] => now;//ボタンが離されるのを待ってる
	}
}


上のコードの

trackSelect[index] => now;

が慣れないと気持ち悪いんですけども。

10::ms => now;

みたいな単純な時間単位のsleep的な使い方以外に、プロセスを適切な時間(次回のイベントがトリガーされるまで)だけ待つっていうした使い方ができて、今回はこっちです。


nowはChucKで重要なスペシャルワードなんで、詳しいことはここ見てくださいー。


そんなこんなで、ボタンパッドだけの操作を補完するのにUIとHIDのキー入力のコード書いてたら、Monomeアプリ完成しないんですけども。。。たいした機能とか無いのにさ。