You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

2224 lines
49 KiB

import java.awt.Robot;
import java.awt.event.InputEvent.*;
class Control {
int x;
int y;
int xsize;
int ysize;
int type;
int state;
int number;
int value;
int velocity;
int softwarevalue;
boolean persistence;
boolean sn;
int timeout;
int idlecolor;
int activecolor;
int controlID;
int page;
int channel = customChannel;
int takeover;
int updatedelay = 50;
boolean TLOCK = false;
boolean TAKEOVER = false;
long threadsSpawned = 0;
long threadsFinished = 0;
Control owner;
boolean isChained = false;
int numberOfChains = 0;
boolean chainSendFlags[] = new boolean[MAXCHAINS];
Control chains[] = new Control[MAXCHAINS];
void up(){}
void down(){}
void on(){}
void off(){}
void send(){}
void setValue(int ivalue){}
void takeoverSetValue(int ivalue){}
void nakedSetValue(int ivalue) {}
void update(){}
void cancelSchedule(){}
void chainTo(Control control, boolean send) {
chains[numberOfChains] = control;
//debug("Chaining "+this+" to "+control);
chainSendFlags[numberOfChains] = send;
numberOfChains++;
isChained = true;
}
void propagateToChainedControls() {
if(isChained) {
for (int i = 0; i < numberOfChains; i++) {
//println("Chained update to c on "+chains[i].page+". now on "+selectedPage);
chains[i].setValue(value);
if (chainSendFlags[i]) chains[i].send();
if (chains[i].page == selectedPage) chains[i].update();
}
}
}
}
class GridSegment extends Control {
void on() {
debug(this+"x="+this.x+" y="+this.y+" on()");
ledOn(x, y, activecolor);
}
void off() {
debug(this+"x="+this.x+" y="+this.y+" off()");
ledOn(x, y, idlecolor);
}
}
class PageButton extends GridSegment {
int number;
PageButton(int inumber) {
page = selectedPage;
//println(this+" on page "+page);
number = inumber;
idlecolor = PAGEBUTTONIDLECOLOR;
activecolor = PAGEBUTTONACTIVECOLOR;
grid[number] = this;
ledOn((number % 8), (int)((float)number / 8), idlecolor);
}
void down() {
ledOn((number % 8), (int)((float)number / 8), activecolor);
loadLayout(number+1);
}
void update() {
x = 8;
y = 7;
off();
}
}
class LED extends GridSegment {
LED(int ix, int iy) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
value = 0;
state = OFF;
timeout = 0;
grid[y*8+x] = this;
idlecolor = INDICATOROFFCOLOR;
activecolor = INDICATORONCOLOR;
ledOn(x, y, idlecolor);
}
void send() {
controlOut(x, y, state);
}
void down() {
}
void up() {
}
void update() {
if (value == 0) {
off();
}
if (value > 0) {
on();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (ivalue > 0) { value = ivalue; state = ON; } else { value = OFF; state = OFF; }
propagateToChainedControls();
}
}
class Button extends GridSegment {
Button(int ix, int iy, int itype) {
controlID = (int)random(1000);
page = selectedPage;
persistence = false;
sn = true;
//println(this+" on page "+page);
x = ix;
y = iy;
type = itype;
value = 0;
velocity = -1;
state = OFF;
timeout = 0;
if (x < 8) {
grid[y*8+x] = this;
}
if (x == 8 && y < 7) {
//debug("Mapping side button:"+this);
grid[65+y] = this;
}
if (type == HOLD) {
idlecolor = BUTTONIDLECOLOR;
activecolor = HOLDONCOLOR;
}
if (type == TOGGLE) {
idlecolor = TOGGLEOFFCOLOR;
activecolor = TOGGLEONCOLOR;
}
ledOn(x, y, idlecolor);
}
void setVelocity(int vel) {
velocity = vel;
}
void send() {
debug("Velocity is "+velocity);
if (channel != 0) outputChannel = channel-1;
if (velocity == -1) controlOut(x, y, state);
if (velocity != -1 && state == ON) controlOut(x, y, velocity);
if (velocity != -1 && state == OFF) controlOut(x, y, state);
}
void down() {
sn = false;
if (type == HOLD) {
state = ON;
setValue(ON);
send();
if (!persistence) on();
}
if (type == TOGGLE) {
if (state == OFF) {
state = ON;
send();
if (!persistence) on();
setValue(ON);
} else if (state == ON) {
state = OFF;
send();
if (!persistence) off();
setValue(OFF);
}
}
}
void up() {
sn = false;
if (type == HOLD) {
//state = OFF;
setValue(OFF);
send();
if (!persistence) off();
}
}
void update() {
debug("sn "+sn);
if (value == 0) {
off();
}
if (value == 127 || softwarevalue == 127) {
on();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
softwarevalue = ivalue;
if (ivalue > 0) { value = 127; state = ON; } else { value = 0; state = OFF; }
propagateToChainedControls();
sn = true;
}
}
class Note extends GridSegment {
int note;
int vel;
boolean sendoff = false;
boolean toggle = false;
Note(int ix, int iy, int octave, String note, int vel) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
value = 0;
state = OFF;
timeout = 0;
idlecolor = NOTEIDLECOLOR;
activecolor = NOTEACTIVECOLOR;
this.note = addOctave(parseNote(note), octave);
this.vel = vel;
if (x < 8) {
grid[y*8+x] = this;
}
if (x == 8 && y < 7) {
//debug("Mapping side button:"+this);
grid[65+y] = this;
}
ledOn(x, y, idlecolor);
}
Note(int ix, int iy, int midi, int vel) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
value = 0;
state = OFF;
timeout = 0;
idlecolor = NOTEIDLECOLOR;
activecolor = NOTEACTIVECOLOR;
this.note = midi;
this.vel = vel;
if (x < 8) {
grid[y*8+x] = this;
}
if (x == 8 && y < 7) {
//debug("Mapping side button:"+this);
grid[65+y] = this;
}
ledOn(x, y, idlecolor);
}
int parseNote(String note) {
note = note.toLowerCase();
if (note.equals("c")) return 0;
if (note.equals("c#")) return 1;
if (note.equals("d")) return 2;
if (note.equals("d#")) return 3;
if (note.equals("e")) return 4;
if (note.equals("f")) return 5;
if (note.equals("f#")) return 6;
if (note.equals("g")) return 7;
if (note.equals("g#")) return 8;
if (note.equals("a")) return 9;
if (note.equals("a#")) return 10;
if (note.equals("b")) return 11;
return 0;
}
int addOctave(int note, int octave) {
octave = octave+1;
return note+(octave*12);
}
void send() {
if (channel != 0) outputChannel = channel-1;
if (sendoff) {
noteOut(note, 0);
sendoff = false;
} else {
//debug("sendOn");
noteOut(note, vel);
}
}
void sendOff() {
if (channel != 0) outputChannel = channel-1;
//debug("sendOff");
noteOut(note, 0);
}
void down() {
if (!toggle) {
send();
on();
} else {
if (state == OFF) {
send();
on();
state = ON;
} else if (state == ON) {
sendOff();
off();
state = OFF;
}
}
}
void up() {
if (!toggle) {
sendOff();
off();
}
}
void update() {
if (value == 0) {
off();
}
if (value == 127) {
on();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
value = ivalue;
if (ivalue == 0) {
sendoff = true;
}
propagateToChainedControls();
}
}
class CC extends GridSegment {
int note;
int vel;
boolean toggle;
boolean sendoff = false;
CC(int ix, int iy, int cc, int vel) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
value = 0;
state = OFF;
timeout = 0;
idlecolor = CCIDLECOLOR;
activecolor = CCACTIVECOLOR;
this.note = cc;
this.vel = vel;
toggle = false;
if (x < 8) {
grid[y*8+x] = this;
}
if (x == 8 && y < 7) {
//debug("Mapping side button:"+this);
grid[65+y] = this;
}
ledOn(x, y, idlecolor);
}
void send() {
if (channel != 0) outputChannel = channel-1;
if (sendoff) {
sendOff();
sendoff = false;
} else {
//debug("sendOn");
controlOut(note, vel);
}
}
void sendOff() {
//debug("sendOff");
//controlOut(note, 0);
}
void down() {
send();
on();
}
void up() {
sendOff();
off();
}
void update() {
if (value == 0) {
off();
}
if (value == 127) {
on();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
value = ivalue;
if (ivalue == 0) {
sendoff = true;
}
propagateToChainedControls();
}
}
class PC extends GridSegment {
int note;
int vel;
boolean sendoff = false;
PC(int ix, int iy, int program) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
value = 0;
state = OFF;
timeout = 0;
idlecolor = PCIDLECOLOR;
activecolor = PCACTIVECOLOR;
this.note = program;
if (x < 8) {
grid[y*8+x] = this;
}
if (x == 8 && y < 7) {
//debug("Mapping side button:"+this);
grid[65+y] = this;
}
ledOn(x, y, idlecolor);
}
void send() {
if (channel != 0) outputChannel = channel-1;
if (sendoff) {
sendOff();
sendoff = false;
} else {
//debug("sendOn");
programOut(note);
}
}
void sendOff() {
//debug("sendOff");
//controlOut(note, 0);
}
void down() {
send();
on();
}
void up() {
sendOff();
off();
}
void update() {
if (value == 0) {
off();
}
if (value == 127) {
on();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
value = ivalue;
if (ivalue == 0) {
sendoff = true;
}
propagateToChainedControls();
}
}
class Kbd extends GridSegment {
int note;
int vel;
boolean sendoff = false;
Robot robot;
int keys[];
Kbd(int ix, int iy, String keystring) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
value = 0;
state = OFF;
timeout = 0;
idlecolor = KBDIDLECOLOR;
activecolor = KBDACTIVECOLOR;
try {
robot = new Robot();
} catch (AWTException e) {
debug("Exception while creating robot "+e);
}
String keysS[] = split(keystring, "+");
keys = new int[keysS.length];
for (int i = 0; i < keys.length; i++) {
keys[i] = parseKey(keysS[i]);
}
if (x < 8) {
grid[y*8+x] = this;
}
if (x == 8 && y < 7) {
//debug("Mapping side button:"+this);
grid[65+y] = this;
}
ledOn(x, y, idlecolor);
}
int parseKey(String keystr) {
if (keystr.equals("shift")) return KeyEvent.VK_SHIFT;
if (keystr.equals("control")) return KeyEvent.VK_CONTROL;
if (keystr.equals("alt")) return KeyEvent.VK_ALT;
if (keystr.equals("altgr")) return KeyEvent.VK_ALT_GRAPH;
if (keystr.equals("command")) return KeyEvent.VK_META;
if (keystr.equals("1")) return KeyEvent.VK_1;
if (keystr.equals("2")) return KeyEvent.VK_2;
if (keystr.equals("3")) return KeyEvent.VK_3;
if (keystr.equals("4")) return KeyEvent.VK_4;
if (keystr.equals("5")) return KeyEvent.VK_5;
if (keystr.equals("6")) return KeyEvent.VK_6;
if (keystr.equals("7")) return KeyEvent.VK_7;
if (keystr.equals("8")) return KeyEvent.VK_8;
if (keystr.equals("9")) return KeyEvent.VK_9;
if (keystr.equals("0")) return KeyEvent.VK_0;
if (keystr.equals("a")) return KeyEvent.VK_A;
if (keystr.equals("b")) return KeyEvent.VK_B;
if (keystr.equals("c")) return KeyEvent.VK_C;
if (keystr.equals("d")) return KeyEvent.VK_D;
if (keystr.equals("e")) return KeyEvent.VK_E;
if (keystr.equals("f")) return KeyEvent.VK_F;
if (keystr.equals("g")) return KeyEvent.VK_G;
if (keystr.equals("h")) return KeyEvent.VK_H;
if (keystr.equals("i")) return KeyEvent.VK_I;
if (keystr.equals("j")) return KeyEvent.VK_J;
if (keystr.equals("k")) return KeyEvent.VK_K;
if (keystr.equals("l")) return KeyEvent.VK_L;
if (keystr.equals("m")) return KeyEvent.VK_M;
if (keystr.equals("n")) return KeyEvent.VK_N;
if (keystr.equals("o")) return KeyEvent.VK_O;
if (keystr.equals("p")) return KeyEvent.VK_P;
if (keystr.equals("q")) return KeyEvent.VK_Q;
if (keystr.equals("r")) return KeyEvent.VK_R;
if (keystr.equals("s")) return KeyEvent.VK_S;
if (keystr.equals("t")) return KeyEvent.VK_T;
if (keystr.equals("u")) return KeyEvent.VK_U;
if (keystr.equals("v")) return KeyEvent.VK_V;
if (keystr.equals("w")) return KeyEvent.VK_W;
if (keystr.equals("x")) return KeyEvent.VK_X;
if (keystr.equals("y")) return KeyEvent.VK_Y;
if (keystr.equals("z")) return KeyEvent.VK_Z;
if (keystr.equals("f1")) return KeyEvent.VK_F1;
if (keystr.equals("f2")) return KeyEvent.VK_F2;
if (keystr.equals("f3")) return KeyEvent.VK_F3;
if (keystr.equals("f4")) return KeyEvent.VK_F4;
if (keystr.equals("f5")) return KeyEvent.VK_F5;
if (keystr.equals("f6")) return KeyEvent.VK_F6;
if (keystr.equals("f7")) return KeyEvent.VK_F7;
if (keystr.equals("f8")) return KeyEvent.VK_F8;
if (keystr.equals("f9")) return KeyEvent.VK_F9;
if (keystr.equals("f10")) return KeyEvent.VK_F10;
if (keystr.equals("f11")) return KeyEvent.VK_F11;
if (keystr.equals("f12")) return KeyEvent.VK_F12;
if (keystr.equals("f13")) return KeyEvent.VK_F13;
if (keystr.equals("f14")) return KeyEvent.VK_F14;
if (keystr.equals("f15")) return KeyEvent.VK_F15;
if (keystr.equals("f16")) return KeyEvent.VK_F16;
if (keystr.equals("f17")) return KeyEvent.VK_F17;
if (keystr.equals("f18")) return KeyEvent.VK_F18;
if (keystr.equals("f19")) return KeyEvent.VK_F19;
if (keystr.equals("esc")) return KeyEvent.VK_ESCAPE;
if (keystr.equals("space")) return KeyEvent.VK_SPACE;
if (keystr.equals("enter")) return KeyEvent.VK_ENTER;
if (keystr.equals("tab")) return KeyEvent.VK_TAB;
if (keystr.equals("backspace")) return KeyEvent.VK_BACK_SPACE;
if (keystr.equals("delete")) return KeyEvent.VK_DELETE;
if (keystr.equals("caps")) return KeyEvent.VK_CAPS_LOCK;
if (keystr.equals("down")) return KeyEvent.VK_DOWN;
if (keystr.equals("up")) return KeyEvent.VK_UP;
if (keystr.equals("left")) return KeyEvent.VK_LEFT;
if (keystr.equals("right")) return KeyEvent.VK_RIGHT;
if (keystr.equals(",")) return KeyEvent.VK_COMMA;
if (keystr.equals(".")) return KeyEvent.VK_PERIOD;
if (keystr.equals("+")) return KeyEvent.VK_PLUS;
if (keystr.equals("-")) return KeyEvent.VK_MINUS;
return 0;
}
void send() {
for (int i = 0; i < keys.length; i++) {
if (keys[i] != 0) {
debug("Sending keyPress "+keys[i]);
robot.keyPress(keys[i]);
}
}
}
void sendOff() {
for (int i = 0; i < keys.length; i++) {
if (keys[i] != 0) {
robot.keyRelease(keys[i]);
}
}
}
void down() {
send();
on();
}
void up() {
sendOff();
off();
}
void update() {
if (value == 0) {
off();
}
if (value == 127) {
on();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
value = ivalue;
if (ivalue == 0) {
sendoff = true;
}
propagateToChainedControls();
}
}
class FaderSegment extends GridSegment {
Fader owner;
FaderSegment(int ix, int iy, Fader iowner) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
owner = iowner;
controlID = (int)random(1000);
grid[y*8+x] = this;
idlecolor = FADERIDLECOLOR;
activecolor = FADERACTIVECOLOR;
off();
}
void down() {
owner.faderAction(this);
}
void update() {
if (x == owner.x && y == owner.y) {
owner.update();
}
}
void send() {
if (x == owner.x && y == owner.y) {
owner.send();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (x == owner.x && y == owner.y) {
owner.nakedSetValue(ivalue);
}
}
void chainTo(Control control, boolean send) {
owner.chainTo(control, send);
}
void propagateToChainedControls() {
owner.propagateToChainedControls();
}
}
class Fader extends Control {
FaderSegment[] segments;
long lastupdate;
boolean schedule;
void faderAction(FaderSegment sender){}
boolean canUpdate() {
long now = (new Date()).getTime();
debug("l "+lastupdate);
debug("n "+now);
debug("d "+(now-lastupdate));
if (now - lastupdate < 100) {
lastupdate = now;
return false;
} else {
return true;
}
}
void schedule() {
schedule = true;
new Scheduler(this);
}
void cancelSchedule() {
schedule = false;
}
boolean hasSchedule() {
return schedule;
}
}
class XFader extends Fader {
int sx;
int lastsx;
XFader(int ix, int iy, int ixsize) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
sx = x;
lastsx = -1;
takeover = 0;
segments = new FaderSegment[xsize];
for (int i = 0; i < xsize; i++) {
segments[i] = new FaderSegment(x+i, y, this);
}
grid[y*8+x].on();
}
void faderAction(FaderSegment sender) {
sx = sender.x;
float relx = sx - x;
float quantum = relx * (1 / ((float)xsize - 1));
float amount = ((relx + quantum) / (float)xsize) * 127;
setValue((int)amount);
}
void update() {
//if (lastsx == sx && !hasSchedule()) schedule();
if (lastsx != sx || canUpdate()) {
if (page == selectedPage) {
for(int i = 0; i < xsize; i++) {
if (i <= sx) { grid[y*8+x+i].on(); } else { grid[y*8+x+i].off(); }
}
lastsx = sx;
lastupdate = (new Date()).getTime();
}
}
}
void send() {
if (channel != 0) outputChannel = channel-1;
controlOut(x, y, value);
}
void setTakeover(int itakeover) {
//debug("setTakeover()");
takeover = itakeover;
}
void nakedSetValue(int ivalue) {
if (TAKEOVER == false) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
propagateToChainedControls();
} else {
//debug("nakedSetValueX() blocked because takeover is in progress.");
}
}
void takeoverSetValue(int ivalue) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
send();
if (lastsx != sx) update();
propagateToChainedControls();
}
void setValue(int ivalue) {
if (takeover == 0) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
send();
if (lastsx != sx) update();
propagateToChainedControls();
} else {
//debug("Delegating control to takeover routine");
takeover(ivalue);
}
}
void takeover(int ivalue) {
threadsSpawned++;
TakeOver takeover = new TakeOver(this, ivalue, this.takeover);
}
}
class IXFader extends Fader {
int sx;
int lastsx;
IXFader(int ix, int iy, int ixsize) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
sx = 0;
lastsx = -1;
takeover = 0;
segments = new FaderSegment[xsize];
for (int i = 0; i < xsize; i++) {
segments[i] = new FaderSegment(x+i, y, this);
}
grid[y*8+x].on();
}
void faderAction(FaderSegment sender) {
sx = sender.x;
float relx = sx - x;
float quantum = relx * (1 / ((float)xsize - 1));
float amount = ((relx + quantum) / (float)xsize) * 127;
setValue(127-(int)amount);
}
void update() {
//if (lastsx == sx && !hasSchedule()) schedule();
if (lastsx != sx || canUpdate()) {
if (page == selectedPage) {
for(int i = xsize-1; i >= 0; i--) {
debug("sx="+((xsize-1)-sx)+" i="+i);
if (i >= (xsize-1)-sx) { grid[y*8+x+i].on(); } else { grid[y*8+x+i].off(); }
//if (i <= sx) { grid[y*8+x+i].on(); } else { grid[y*8+x+i].off(); }
}
lastsx = sx;
lastupdate = (new Date()).getTime();
}
}
}
void send() {
if (channel != 0) outputChannel = channel-1;
controlOut(x, y, value);
}
void setTakeover(int itakeover) {
//debug("setTakeover()");
takeover = itakeover;
}
void nakedSetValue(int ivalue) {
if (TAKEOVER == false) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
propagateToChainedControls();
} else {
//debug("nakedSetValueX() blocked because takeover is in progress.");
}
}
void takeoverSetValue(int ivalue) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
send();
if (lastsx != sx) update();
propagateToChainedControls();
}
void setValue(int ivalue) {
if (takeover == 0) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
send();
if (lastsx != sx) update();
propagateToChainedControls();
} else {
//debug("Delegating control to takeover routine");
takeover(ivalue);
}
}
void takeover(int ivalue) {
threadsSpawned++;
TakeOver takeover = new TakeOver(this, ivalue, this.takeover);
}
}
class YFader extends Fader {
int sy;
int lastsy;
YFader(int ix, int iy, int iysize) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
ysize = iysize;
sy = y;
lastsy = -1;
value = 0;
segments = new FaderSegment[ysize];
for (int i = 0; i < ysize; i++) {
segments[i] = new FaderSegment(x, y - i, this);
}
grid[y*8+x].on();
}
void faderAction(FaderSegment sender) {
sy = sender.y;
float rely = sy - y;
float quantum = rely * (1 / ((float)ysize - 1));
float amount = ((rely + quantum) / (float)ysize) * 127;
setValue(0 - ((int)amount));
}
void update() {
//if (lastsy == sy && !hasSchedule()) schedule();
if (lastsy != sy || canUpdate()) {
if (page == selectedPage) {
for(int i = y; i > y - ysize; i--) {
if (i >= sy) { grid[i*8+x].on(); } else { grid[i*8+x].off(); }
}
lastsy = sy;
lastupdate = (new Date()).getTime();
}
}
}
void send() {
if (channel != 0) outputChannel = channel-1;
controlOut(x, y, value);
}
void setTakeover(int itakeover) {
//debug("setTakeover()");
takeover = itakeover;
}
void nakedSetValue(int ivalue) {
if (TAKEOVER == false) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
propagateToChainedControls();
} else {
//debug("nakedSetValue() blocked because takeover is in progress.");
}
}
void takeoverSetValue(int ivalue) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
send();
//debug("sy "+sy+" lastsy "+lastsy);
if (lastsy != sy) update();
propagateToChainedControls();
}
void setValue(int ivalue) {
if (takeover == 0) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
send();
if (lastsy != sy) update();
propagateToChainedControls();
} else {
//debug("Delegating control to takeover routine");
takeover(ivalue);
}
}
void takeover(int ivalue) {
threadsSpawned++;
TakeOver takeover = new TakeOver(this, ivalue, this.takeover);
}
}
class IYFader extends Fader {
int sy;
int lastsy;
IYFader(int ix, int iy, int iysize) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
ysize = iysize;
sy = y;
lastsy = -1;
value = 0;
segments = new FaderSegment[ysize];
for (int i = 0; i < ysize; i++) {
segments[i] = new FaderSegment(x, y - i, this);
}
grid[y*8+x].on();
}
void faderAction(FaderSegment sender) {
sy = sender.y;
debug("!! sy="+sy);
float rely = sy - y;
float quantum = rely * (1 / ((float)ysize - 1));
float amount = ((rely + quantum) / (float)ysize) * 127;
setValue(127 + ((int)amount));
debug("!! value="+(127 + ((int)amount)));
}
void update() {
if (lastsy != sy || canUpdate()) {
if (page == selectedPage) {
for(int i = 0; i < ysize; i++) {
int pos = y - sy;
pos = (ysize-1)-pos;
debug("i="+i+" sy="+sy+" pos="+pos);
if (i >= pos ) { grid[(y-i)*8+x].on(); } else { grid[(y-i)*8+x].off(); }
}
lastsy = sy;
lastupdate = (new Date()).getTime();
}
}
}
void send() {
if (channel != 0) outputChannel = channel-1;
controlOut(x, y, value);
}
void setTakeover(int itakeover) {
//debug("setTakeover()");
takeover = itakeover;
}
void nakedSetValue(int ivalue) {
if (TAKEOVER == false) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
propagateToChainedControls();
} else {
//debug("nakedSetValue() blocked because takeover is in progress.");
}
}
void takeoverSetValue(int ivalue) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
send();
//debug("sy "+sy+" lastsy "+lastsy);
if (lastsy != sy) update();
propagateToChainedControls();
}
void setValue(int ivalue) {
if (takeover == 0) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
send();
if (lastsy != sy) update();
propagateToChainedControls();
} else {
//debug("Delegating control to takeover routine");
takeover(ivalue);
}
}
void takeover(int ivalue) {
threadsSpawned++;
TakeOver takeover = new TakeOver(this, ivalue, this.takeover);
}
}
class SliderSegment extends GridSegment {
Slider owner;
SliderSegment(int ix, int iy, Slider iowner) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
owner = iowner;
grid[y*8+x] = this;
idlecolor = SLIDERIDLECOLOR;
activecolor = SLIDERACTIVECOLOR;
off();
}
void down() {
owner.sliderAction(this);
}
void up() {
owner.liftFinger(this);
}
void update() {
off();
}
void send() {
if (x == owner.x && y == owner.y) {
owner.send();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (x == owner.x && y == owner.y) {
owner.setValue(ivalue);
}
}
void chainTo(Control control, boolean send) {
owner.chainTo(control, send);
}
void propagateToChainedControls() {
owner.propagateToChainedControls();
}
}
class Slider extends Control {
SliderSegment[] segments;
void sliderAction(SliderSegment sender){}
void liftFinger(SliderSegment sender){};
void send() {
if (channel != 0) outputChannel = channel-1;
controlOut(x, y, value);
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
value = ivalue;
propagateToChainedControls();
}
}
class XSlider extends Slider {
int lastSegment;
int segment;
int granularity;
XSlider(int ix, int iy, int ixsize, int igranularity) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
value = SLIDERDEFAULTVALUE;
granularity = igranularity;
segments = new SliderSegment[xsize];
for (int i = 0; i < xsize; i++) {
segments[i] = new SliderSegment(x+i, y, this);
}
}
void sliderAction(SliderSegment sender) {
segment = sender.x;
if (lastSegment - 1 == segment) {
decrease();
//debug("Decreasing "+this+" to "+value);
}
if (lastSegment + 1 == segment) {
increase();
//debug("Increasing "+this+" to "+value);
}
sender.on();
lastSegment = segment;
}
void liftFinger(SliderSegment sender) {
sender.off();
}
void increase() {
if (value < 127) {
value += granularity;
}
if (value > 127) {
value = 127;
}
send();
propagateToChainedControls();
}
void decrease() {
if (value > 0) {
value -= granularity;
}
if (value < 0) {
value = 0;
}
send();
propagateToChainedControls();
}
}
class YSlider extends Slider {
int lastSegment;
int segment;
int granularity;
YSlider(int ix, int iy, int iysize, int igranularity) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
ysize = iysize;
value = SLIDERDEFAULTVALUE;
granularity = igranularity;
segments = new SliderSegment[ysize];
for (int i = 0; i < ysize; i++) {
segments[i] = new SliderSegment(x, y - i, this);
}
}
void sliderAction(SliderSegment sender) {
segment = sender.y;
if (lastSegment - 1 == segment) {
increase();
}
if (lastSegment + 1 == segment) {
decrease();
}
sender.on();
lastSegment = segment;
}
void liftFinger(SliderSegment sender) {
sender.off();
}
void increase() {
if (value < 127) {
value += granularity;
}
if (value > 127) {
value = 127;
}
send();
propagateToChainedControls();
}
void decrease() {
if (value > 0) {
value -= granularity;
}
if (value < 0) {
value = 0;
}
send();
propagateToChainedControls();
}
}
class PadSegment extends GridSegment {
Pad owner;
PadSegment(int ix, int iy, Pad iowner) {
x = ix;
y = iy;
owner = iowner;
grid[y*8+x] = this;
idlecolor = PADOFFCOLOR;
activecolor = PADONCOLOR;
off();
}
void down() {
owner.padAction(this);
}
void update() {
owner.update(this);
}
void send() {
if (x == owner.x && y == owner.y) {
owner.sendX();
}
if (x == owner.x+1 && y == owner.y) {
owner.sendY();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (x == owner.x && y == owner.y) {
owner.nakedSetValueX(ivalue);
}
if (x == owner.x+1 && y == owner.y) {
owner.nakedSetValueY(ivalue);
}
}
void chainTo(Control control, boolean send) {
owner.chainTo(control, send);
}
void propagateToChainedControls() {
owner.propagateToChainedControls();
}
}
class Pad extends Control {
PadSegment[] padSegments;
int sx;
int sy;
int lastsx;
int lastsy;
int xvalue;
int yvalue;
boolean invertx = false;
boolean inverty = false;
boolean TAKEOVER;
long threadsSpawned = 0;
long threadsFinished = 0;
Pad(int ix, int iy, int ixsize, int iysize) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
ysize = iysize;
sx = x;
sy = y+ysize-1;
takeover = 0;
yvalue = 0;
xvalue = 0;
lastsx = x;
lastsy = y+ysize-1;
padSegments = new PadSegment[xsize*ysize];
for (int yi = 0; yi < ysize; yi++) {
for (int xi = 0; xi < xsize; xi++) {
padSegments[yi*ysize+xi] = new PadSegment(xi+x, yi+y, this);
}
}
}
void padAction(PadSegment sender) {
//debug("padAction()");
sy = sender.y;
float rely = sy - y;
float quantum = rely * (1 / ((float)ysize - 1));
float amounty = 127-((rely + quantum) / (float)ysize) * 127;
sx = sender.x;
float relx = sx - x;
quantum = relx * (1 / ((float)xsize - 1));
float amountx = ((relx + quantum) / (float)xsize) * 127;
setValue((int)amountx, (int)amounty);
}
void send() {
sendX();
sendY();
}
void sendX() {
if (channel != 0) outputChannel = channel-1;
if (!invertx) controlOut(x, y, xvalue);
if (invertx) controlOut(x, y, 127-xvalue);
}
void sendY() {
if (channel != 0) outputChannel = channel-1;
if (!inverty) controlOut(x+1, y, yvalue);
if (inverty) controlOut(x+1, y, 127-yvalue);
}
void setTakeover(int takeover) {
this.takeover = takeover;
}
void invertx() {
invertx = true;
}
void inverty() {
inverty = true;
}
void nakedSetValueX(int ivalue) {
if (invertx) ivalue = 127-ivalue;
if (TAKEOVER == false) {
float step = 127 / (xsize-1);
sx = x+(int)(ivalue / step);
xvalue = ivalue;
propagateToChainedControls();
//debug("nakedSetValueX() succeeded.");
} else {
//debug("nakedSetValueX() blocked because takeover is in progress.");
}
}
void nakedSetValueY(int ivalue) {
if (inverty) ivalue = 127-ivalue;
if (TAKEOVER == false) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = (ysize-1)+(y - rely);
yvalue = ivalue;
propagateToChainedControls();
//debug("nakedSetValueY() succeeded.");
} else {
//debug("nakedSetValueY() blocked because takeover is in progress.");
}
}
void takeoverSetValue(int ixvalue, int iyvalue) {
float step = 127 / (ysize-1);
int rely = ((int)(iyvalue / step));
sy = (ysize-1)+(y - rely);
yvalue = iyvalue;
step = 127 / (xsize-1);
sx = x+(int)(ixvalue / step);
xvalue = ixvalue;
//debug("xvalue = "+xvalue+". sx = "+sx);
//debug("yvalue = "+yvalue+". sy = "+sy);
send();
if (lastsy != sy || lastsx != sx) update();
propagateToChainedControls();
}
void setValue(int ixvalue, int iyvalue) {
if (takeover == 0) {
float step = 127 / (ysize-1);
int rely = ((int)(iyvalue / step));
sy = (ysize-1)+(y - rely);
yvalue = iyvalue;
step = 127 / (xsize-1);
sx = x+(int)(ixvalue / step);
xvalue = ixvalue;
//debug("xvalue = "+xvalue+". sx = "+sx);
//debug("yvalue = "+yvalue+". sy = "+sy);
send();
if (lastsy != sy || lastsx != sx) update();
propagateToChainedControls();
} else {
//debug("Delegating control to takeover routine");
takeover(ixvalue, iyvalue);
}
}
void takeover(int ixvalue, int iyvalue) {
threadsSpawned++;
TakeOver2d takeover = new TakeOver2d(this, ixvalue, iyvalue, this.takeover);
}
void update() {
if (page == selectedPage) {
//debug("update() sx="+sx+" sy="+sy);
grid[lastsx+lastsy*8].off();
grid[sx+sy*8].on();
lastsx = sx;
lastsy = sy;
}
}
void update(PadSegment sender) {
//debug("update("+sender+") sx="+sx+" sy="+sy);
if ((sender.x == x && sender.y == y) || (sender.x-1 == x && sender.y == y)) {
//debug("is the case");
if (sender.x == sx && sender.y == sy) { sender.on(); } else { sender.off(); }
grid[sx+sy*8].on();
if (lastsx != sx || lastsy != sy) {
grid[lastsx+lastsy*8].off();
lastsx = sx;
lastsy = sy;
}
} else {
//debug("not the case");
if (sender.x == sx && sender.y == sy) sender.on();
if (sender.x != sx || sender.y != sy) sender.off();
}
/*lastsx = sx;
lastsy = sy;*/
}
}
class Drumrack extends Control {
Drumrack(int ix, int iy, int ixsize, int iysize, int startOctave, String startNote, int vel, boolean invert) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
ysize = iysize;
Note note;
int snote = addOctave(parseNote(startNote), startOctave);
if (invert) {
for (int yi = 0; yi < ysize; yi++) {
for (int xi = 0; xi < xsize; xi++) {
new Note(xi+x, ((ysize-1)-yi)+y, snote, vel);
snote++;
}
}
} else {
for (int yi = 0; yi < ysize; yi++) {
for (int xi = 0; xi < xsize; xi++) {
new Note(xi+x, yi+y, snote, vel);
snote++;
}
}
}
}
int parseNote(String note) {
note = note.toLowerCase();
if (note.equals("c")) return 0;
if (note.equals("c#")) return 1;
if (note.equals("d")) return 2;
if (note.equals("d#")) return 3;
if (note.equals("e")) return 4;
if (note.equals("f")) return 5;
if (note.equals("f#")) return 6;
if (note.equals("g")) return 7;
if (note.equals("g#")) return 8;
if (note.equals("a")) return 9;
if (note.equals("a#")) return 10;
if (note.equals("b")) return 11;
return 0;
}
int addOctave(int note, int octave) {
octave = octave+1;
return note+(octave*12);
}
}
class MeterSegment extends GridSegment {
Meter owner;
MeterSegment(int ix, int iy, Meter iowner) {
page = selectedPage;
x = ix;
y = iy;
owner = iowner;
controlID = (int)random(1000);
grid[y*8+x] = this;
idlecolor = METERIDLECOLOR;
activecolor = METERACTIVECOLOR;
off();
}
void update() {
if (x == owner.x && y == owner.y) {
owner.update();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (x == owner.x && y == owner.y) {
owner.nakedSetValue(ivalue);
}
}
void chainTo(Control control, boolean send) {
owner.chainTo(control, send);
}
void propagateToChainedControls() {
owner.propagateToChainedControls();
}
}
class Meter extends Control {
MeterSegment[] segments;
long lastupdate;
boolean canUpdate() {
long now = (new Date()).getTime();
if (now - lastupdate > updatedelay) {
lastupdate = now;
return true;
} else {
return false;
}
}
}
class XMeter extends Meter {
int sx;
float sxf;
int lastsx;
float lastsxf;
XMeter(int ix, int iy, int ixsize) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
sx = x;
lastsx = -1;
takeover = 0;
segments = new MeterSegment[xsize];
for (int i = 0; i < xsize; i++) {
segments[i] = new MeterSegment(x+i, y, this);
}
grid[y*8+x].on();
}
void update() {
if (canUpdate()) {
//debug("go");
if (page == selectedPage) {
for(int i = 0; i < xsize; i++) {
if (i != sx && i != sx+1) {
grid[y*8+x+i].off();
}
if (i == sx+1 && !(sxf - sx >= 0.56) && !(((sxf - sx) > 0.43 && (sxf - sx) < 0.56) && sx != xsize-1)) {
grid[y*8+x+i].off();
}
if (i == sx) {
if (sxf - sx <= 0.43) {
grid[y*8+x+i].on();
}
if (sxf - sx >= 0.56) {
grid[y*8+x+(i+1)].on();
}
if (((sxf - sx) > 0.43 && (sxf - sx) < 0.56) && sx != xsize-1) {
grid[y*8+x+i].on();
grid[y*8+x+i+1].on();
}
}
}
lastsx = sx;
lastsxf = sxf;
}
} else { /*debug("filtered");*/ }
}
void nakedSetValue(int ivalue) {
float step = 127 / (xsize-1);
sxf = (ivalue / step);
//println(sxf);
sx = (int)sxf;
value = ivalue;
propagateToChainedControls();
}
void setValue(int ivalue) {
float step = 127 / (xsize-1);
sxf = (ivalue / step);
//println(sxf);
sx = (int)sxf;
value = ivalue;
send();
if (lastsxf != sxf) update();
propagateToChainedControls();
}
}
class YMeter extends Meter {
int sy;
int lastsy;
float syf;
float lastsyf;
YMeter(int ix, int iy, int iysize) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
ysize = iysize;
sy = y;
lastsy = -1;
value = 0;
segments = new MeterSegment[ysize];
for (int i = 0; i < ysize; i++) {
segments[i] = new MeterSegment(x, y - i, this);
}
grid[y*8+x].on();
}
void update() {
//debug("diff: "+abs((lastsy-lastsyf) - (sy-syf)));
if (page == selectedPage && canUpdate()) {
for(int i = y; i >= y-(ysize-1); i--) {
if (i != sy && i != sy-1) {
grid[i*8+x].off();
//debug("turning off 0");
}
if (i == sy-1 && !(sy - syf >= 0.56) && !(((sy - syf) > 0.43 && (syf - sy) < 0.56))) {
grid[(i)*8+x].off();
}
if (i == sy) {
if (sy - syf <= 0.43) {
grid[i*8+x].on();
//debug("turning on 0");
}
if (sy - syf >= 0.56) {
grid[(i-1)*8+x].on();
//debug("turning on -1");
}
if (((sy - syf) > 0.43 && (syf - sy) < 0.56) && sy != y-ysize-1) {
grid[i*8+x].on();
grid[(i-1)*8+x].on();
//debug("turning on both");
}
}
}
lastsy = sy;
lastsyf = syf;
}
}
void nakedSetValue(int ivalue) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
syf = y - abs((ivalue / step));
sy = y - rely;
//debug("syf: "+syf);
value = ivalue;
propagateToChainedControls();
}
void setValue(int ivalue) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
syf = y - abs((ivalue / step));
//debug("syf: "+syf);
value = ivalue;
send();
if (lastsyf != syf) update();
propagateToChainedControls();
}
}
class ProgressSegment extends GridSegment {
Progress owner;
ProgressSegment(int ix, int iy, Progress iowner) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
owner = iowner;
controlID = (int)random(1000);
grid[y*8+x] = this;
idlecolor = PROGRESSIDLECOLOR;
activecolor = PROGRESSACTIVECOLOR;
off();
}
void update() {
if (x == owner.x && y == owner.y) {
owner.update();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (x == owner.x && y == owner.y) {
owner.nakedSetValue(ivalue);
}
}
void chainTo(Control control, boolean send) {
owner.chainTo(control, send);
}
void propagateToChainedControls() {
owner.propagateToChainedControls();
}
}
class Progress extends Control {
ProgressSegment[] segments;
long lastupdate;
boolean canUpdate() {
long now = (new Date()).getTime();
if (now - lastupdate > updatedelay) {
lastupdate = now;
return true;
} else {
return false;
}
}
}
class XProgress extends Progress {
int sx;
int lastsx;
XProgress(int ix, int iy, int ixsize) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
sx = x;
lastsx = -1;
takeover = 0;
segments = new ProgressSegment[xsize];
for (int i = 0; i < xsize; i++) {
segments[i] = new ProgressSegment(x+i, y, this);
}
grid[y*8+x].on();
}
void update() {
//if (lastsx != sx) {
if (page == selectedPage && canUpdate()) {
for(int i = 0; i < xsize; i++) {
if (i <= sx) { grid[y*8+x+i].on(); } else { grid[y*8+x+i].off(); }
}
lastsx = sx;
}
//}
}
void nakedSetValue(int ivalue) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
propagateToChainedControls();
}
void setValue(int ivalue) {
float step = 127 / (xsize-1);
sx = (int)(ivalue / step);
value = ivalue;
send();
if (lastsx != sx) update();
propagateToChainedControls();
}
}
class YProgress extends Progress {
int sy;
int lastsy;
YProgress(int ix, int iy, int iysize) {
controlID = (int)random(1000);
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
ysize = iysize;
sy = y;
lastsy = -1;
value = 0;
segments = new ProgressSegment[ysize];
for (int i = 0; i < ysize; i++) {
segments[i] = new ProgressSegment(x, y - i, this);
}
grid[y*8+x].on();
}
void update() {
//if (lastsy != sy) {
if (page == selectedPage && canUpdate()) {
for(int i = y; i > y - ysize; i--) {
if (i >= sy) { grid[i*8+x].on(); } else { grid[i*8+x].off(); }
}
lastsy = sy;
}
//}
}
void nakedSetValue(int ivalue) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
propagateToChainedControls();
}
void setValue(int ivalue) {
float step = 127 / (ysize-1);
int rely = ((int)(ivalue / step));
sy = y - rely;
value = ivalue;
send();
if (lastsy != sy) update();
propagateToChainedControls();
}
}
class CrsFaderSegment extends GridSegment {
CrsFader owner;
CrsFaderSegment(int ix, int iy, CrsFader iowner) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
owner = iowner;
controlID = (int)random(1000);
grid[y*8+x] = this;
idlecolor = FADERIDLECOLOR;
activecolor = FADERACTIVECOLOR;
off();
}
void down() {
owner.faderAction(this);
}
void up() {
owner.stopAction();
}
void update() {
if (x == owner.x && y == owner.y) {
owner.update();
}
}
void send() {
if (x == owner.x && y == owner.y) {
owner.send();
}
}
void nakedSetValue(int ivalue) { setValue(ivalue); }
void setValue(int ivalue) {
if (x == owner.x && y == owner.y) {
owner.nakedSetValue(ivalue);
}
}
void chainTo(Control control, boolean send) {
owner.chainTo(control, send);
}
void propagateToChainedControls() {
owner.propagateToChainedControls();
}
}
class CrsFader extends Control {
int sx;
float sxf;
int lastsx;
float lastsxf;
float factor;
boolean running;
CrsFaderSegment[] segments;
long lastupdate;
CrsFader(int ix, int iy, int ixsize) {
page = selectedPage;
//println(this+" on page "+page);
x = ix;
y = iy;
xsize = ixsize;
sx = x;
lastsx = -1;
takeover = 0;
factor = 0;
running = false;
segments = new CrsFaderSegment[xsize];
for (int i = 0; i < xsize; i++) {
segments[i] = new CrsFaderSegment(x+i, y, this);
}
grid[y*8+x].on();
}
void stopAction() {
running = false;
factor = 0;
}
void faderAction(CrsFaderSegment sender) {
if (xsize % 2 != 0) {
int relx = sender.x - x + 1;
int center = abs(round(((float)xsize/2)));
float relpos = ((relx - center)/((float)xsize-1))*2;
debug("CrsFader update. Sender x = "+sender.x+", relx="+relx);
debug("Relative position: "+relpos+", center="+center);
} else {
int relx = sender.x - x + 1;
int center = xsize/2;
float relpos = 0;
if (relx <= center) {
relpos = (center - (relx-1))/(float)center * -1;
} else {
relpos = (relx - center)/(float)center;
}
debug("CrsFader update. Sender x = "+sender.x+", relx="+relx);
debug("Relative position: "+relpos+", center="+center);
factor = relpos;
if (factor != 0 && !running) {
running = true;
spawnThread();
}
}
}
void spawnThread() {
CrsUpdater updater = new CrsUpdater(this);
}
void updateValue() {
int nvalue = (int)(value+(factor*6));
if (nvalue < 0) nvalue = 0;
if (nvalue > 127) nvalue = 127;
setValue(nvalue);
}
boolean canUpdate() {
long now = (new Date()).getTime();
if (now - lastupdate > updatedelay) {
lastupdate = now;
return true;
} else {
return false;
}
}
void update() {
if (canUpdate()) {
//debug("go");
if (page == selectedPage) {
for(int i = 0; i < xsize; i++) {
if (i != sx && i != sx+1) {
grid[y*8+x+i].off();
}
if (i == sx+1 && !(sxf - sx >= 0.56) && !(((sxf - sx) > 0.43 && (sxf - sx) < 0.56) && sx != xsize-1)) {
grid[y*8+x+i].off();
}
if (i == sx) {
if (sxf - sx <= 0.43) {
grid[y*8+x+i].on();
}
if (sxf - sx >= 0.56) {
grid[y*8+x+(i+1)].on();
}
if (((sxf - sx) > 0.43 && (sxf - sx) < 0.56) && sx != xsize-1) {
grid[y*8+x+i].on();
grid[y*8+x+i+1].on();
}
}
}
lastsx = sx;
lastsxf = sxf;
}
} else { /*debug("filtered");*/ }
}
void nakedSetValue(int ivalue) {
if (!running) {
float step = 127 / (xsize-1);
sxf = (ivalue / step);
//println(sxf);
sx = (int)sxf;
value = ivalue;
propagateToChainedControls();
} else {
debug("Blocked because thread is running");
}
}
void setValue(int ivalue) {
float step = 127 / (xsize-1);
sxf = (ivalue / step);
//println(sxf);
sx = (int)sxf;
value = ivalue;
send();
if (lastsxf != sxf) update();
propagateToChainedControls();
}
void send() {
controlOut(x, y, value);
}
}