PageRenderTime 30ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Lemur3/application.windows/source/Lemur3.java

https://bitbucket.org/wraybowling/lemur-clone
Java | 486 lines | 382 code | 53 blank | 51 comment | 54 complexity | 16da00716e0b3aaec51ffb3ce6b2cacf MD5 | raw file
  1. import processing.core.*;
  2. import processing.xml.*;
  3. import TUIO.*;
  4. import rwmidi.*;
  5. import java.applet.*;
  6. import java.awt.*;
  7. import java.awt.image.*;
  8. import java.awt.event.*;
  9. import java.io.*;
  10. import java.net.*;
  11. import java.text.*;
  12. import java.util.*;
  13. import java.util.zip.*;
  14. import java.util.regex.*;
  15. public class Lemur3 extends PApplet {
  16. TuioProcessing tuioClient;
  17. MidiInput input;
  18. MidiOutput output;
  19. float cur_size = 5;
  20. int module_count = 4;
  21. Module[] Modules = new Module[module_count];
  22. PFont font;
  23. public void setup(){
  24. noLoop();
  25. tuioClient = new TuioProcessing(this);
  26. String[] out = RWMidi.getOutputDeviceNames();
  27. println(out);
  28. output = RWMidi.getOutputDevices()[0].createOutput();
  29. String[] in = RWMidi.getInputDeviceNames();
  30. println(in);
  31. input = RWMidi.getInputDevices()[0].createInput(this);
  32. font = loadFont("BitstreamVeraSans-Roman-10.vlw");
  33. textFont(font);
  34. size(640,480);
  35. Modules[0] = new Knob(0,0,320,240,0xffff2040);
  36. Modules[1] = new Button(320,0,320,240,0xff40ff40,true,true);
  37. Modules[2] = new Slider(0,240,320,240,0xff1060e0,"horizontal","absolute");
  38. Modules[3] = new Monome(320,240,320,240,0xffffffff,4,4);
  39. /* Modules[0] = new Knob(0, 0, 160,240,#F54D2F);
  40. Modules[1] = new Knob(160, 0, 160,240,#C3F52F);
  41. Modules[2] = new Knob(320, 0, 160,240,#2FA0F5);
  42. Modules[3] = new Knob(480, 0, 160,240,#4D4D4D);
  43. Modules[4] = new Button(0, 240, 160,240,#F54D2F,true,false);
  44. Modules[5] = new Button(160, 240, 160,240,#C3F52F,true,false);
  45. Modules[6] = new Button(320, 240, 160,240,#2FA0F5,true,false);
  46. Modules[7] = new Button(480, 240, 160,240,#4D4D4D,true,false);*/
  47. }
  48. public void draw(){
  49. background(0xff272624);
  50. strokeWeight(1);
  51. for(int i=0; i< module_count; i++){
  52. Modules[i].draw();
  53. }
  54. smooth();
  55. strokeWeight(2);
  56. Vector tuioCursorList = tuioClient.getTuioCursors();
  57. for (int i=0;i<tuioCursorList.size();i++) {
  58. TuioCursor tcur = (TuioCursor)tuioCursorList.elementAt(i);
  59. Vector pointList = tcur.getPath();
  60. if (pointList.size()>0) {
  61. stroke(23,206,250,33);
  62. noFill();
  63. beginShape();
  64. for (int j=0;j<pointList.size();j++) {
  65. TuioPoint this_point = (TuioPoint)pointList.elementAt(j);
  66. vertex(this_point.getScreenX(width),this_point.getScreenY(height));
  67. }
  68. endShape();
  69. noStroke();
  70. fill(192,192,192);
  71. ellipse( tcur.getScreenX(width), tcur.getScreenY(height),cur_size,cur_size);
  72. fill(255);
  73. text(""+ tcur.getCursorID(), tcur.getScreenX(width)+2, tcur.getScreenY(height)+4);
  74. }
  75. }
  76. }
  77. // ADD
  78. public void addTuioCursor(TuioCursor tcur) {
  79. //print('<');
  80. //println("add cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+ ") " +tcur.getX()+" "+tcur.getY());
  81. Vector pointList = tcur.getPath();
  82. if (pointList.size()>0) {
  83. TuioPoint A = (TuioPoint)pointList.elementAt(0);
  84. for(int i=0; i<module_count; i++){
  85. if(Modules[i].collision(A.getScreenX(width),A.getScreenY(height))){
  86. Modules[i].cursorID = tcur.getCursorID();
  87. Modules[i].addCollision(tcur.getCursorID(),A.getScreenX(width),A.getScreenY(height));
  88. }
  89. }
  90. }
  91. }
  92. // MOVE
  93. public void updateTuioCursor (TuioCursor tcur) {
  94. Vector tuioCursorList = tuioClient.getTuioCursors();
  95. //print(tuioCursorList.size());
  96. //println("update cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+ ") " +tcur.getX()+" "+tcur.getY() +" "+tcur.getMotionSpeed()+" "+tcur.getMotionAccel());
  97. Vector pointList = tcur.getPath();
  98. if (pointList.size()>1) {
  99. TuioPoint A = (TuioPoint)pointList.elementAt(pointList.size()-2);
  100. TuioPoint B = (TuioPoint)pointList.elementAt(pointList.size()-1);
  101. for(int i=0; i<module_count; i++){
  102. if(tcur.getCursorID() == Modules[i].cursorID){
  103. Modules[i].updateCollision(A.getScreenX(width),A.getScreenY(height),B.getScreenX(width),B.getScreenY(height));
  104. }
  105. }
  106. }
  107. }
  108. // REMOVE
  109. public void removeTuioCursor(TuioCursor tcur) {
  110. //print('>');
  111. //println("remove cursor "+tcur.getCursorID()+" ("+tcur.getSessionID()+")");
  112. Vector pointList = tcur.getPath();
  113. if (pointList.size()>0) {
  114. TuioPoint B = (TuioPoint)pointList.elementAt(pointList.size()-1);
  115. for(int i=0; i<module_count; i++){
  116. if(tcur.getCursorID() == Modules[i].cursorID){
  117. Modules[i].cursorID = -1;
  118. Modules[i].removeCollision(tcur.getCursorID());
  119. }
  120. }
  121. }
  122. }
  123. // called after each message bundle
  124. // representing the end of an image frame
  125. public void refresh(TuioTime bundleTime) {
  126. redraw();
  127. }
  128. // i don't care about objects...
  129. public void addTuioObject(TuioObject tobj) {}
  130. public void removeTuioObject(TuioObject tobj) {}
  131. public void updateTuioObject(TuioObject tobj) {}
  132. class Button extends Module{
  133. boolean on, toggleOnAdd, toggleOnRemove;
  134. Button(int x, int y, int w, int h, int c, boolean toggleOnAdd, boolean toggleOnRemove){
  135. super(x,y,w,h,c);
  136. this.toggleOnAdd = toggleOnAdd;
  137. this.toggleOnRemove = toggleOnRemove;
  138. midi_controller = new int[1];
  139. midi_controller[0] = next_available_midi;
  140. next_available_midi++;
  141. }
  142. public void draw(){
  143. super.draw();
  144. if(on){
  145. noStroke();
  146. fill(backlightOn);
  147. rect(x,y,w,h);
  148. fill(c);
  149. int radius = min(w,h) / 2;
  150. smooth();
  151. ellipse(x+w/2, y+h/2, radius, radius);
  152. }else{
  153. fill(backlightOff);
  154. noStroke();
  155. rect(x,y,w,h);
  156. }
  157. }
  158. public void toggle(){
  159. if(!on){
  160. on = true;
  161. output.sendController(0,midi_controller[0],127);
  162. }else{
  163. on = false;
  164. output.sendController(0,midi_controller[0],0);
  165. }
  166. }
  167. public void addCollision(int id, int x, int y){
  168. if(toggleOnAdd){
  169. toggle();
  170. }
  171. }
  172. public void removeCollision(){
  173. if(toggleOnRemove){
  174. toggle();
  175. }
  176. }
  177. }
  178. class Knob extends Module{
  179. float angle = -PI/2;
  180. float radius;
  181. float lowerLimit = -PI - PI / 4.0f;
  182. float upperLimit = PI / 4.0f;
  183. float centerX, centerY;
  184. Knob(int x, int y, int w, int h, int c){
  185. super(x,y,w,h,c);
  186. centerX = x + w/2;
  187. centerY = y + h/2;
  188. this.radius = min(w,h);
  189. midi_controller = new int[1];
  190. midi_controller[0] = next_available_midi;
  191. next_available_midi++;
  192. }
  193. public void draw(){
  194. // super.draw();
  195. smooth();
  196. pushMatrix();
  197. translate(centerX, centerY);
  198. //draw the fill
  199. noStroke();
  200. if(active)
  201. fill(backlightOn);
  202. else
  203. fill(backlightOff);
  204. ellipse(0,0,radius*0.9f,radius*0.9f);
  205. //draw the outline
  206. stroke(c);
  207. noFill();
  208. strokeWeight(1);
  209. ellipse(0,0,radius*0.9f,radius*0.9f);
  210. //draw the progress arc
  211. strokeWeight(radius*0.1f);
  212. strokeCap(SQUARE);
  213. arc(0,0,PApplet.parseInt(radius*0.6f),PApplet.parseInt(radius*0.6f),lowerLimit,angle);
  214. fill(c);
  215. ellipse(0,0,radius*0.1f, radius*0.1f);
  216. popMatrix();
  217. }
  218. public void updateCollision(int ax, int ay, int bx, int by){
  219. float centerX = x+w/2;
  220. float centerY = y+h/2;
  221. float prevAngle = atan2(ay-centerY, ax-centerX);
  222. float thisAngle = atan2(by-centerY, bx-centerX);
  223. float diffAngle = thisAngle - prevAngle;
  224. if(diffAngle >= PI) diffAngle -= TWO_PI;
  225. if(diffAngle <= -PI) diffAngle += TWO_PI;
  226. angle += diffAngle;
  227. angle = min(upperLimit ,angle);
  228. angle = max(lowerLimit ,angle);
  229. output.sendController(0,midi_controller[0],round(map(angle,lowerLimit,upperLimit,0,127)));
  230. }
  231. }
  232. int next_available_midi = 0;
  233. class Module{
  234. long cursorID = -1;
  235. int[] midi_controller;
  236. int x, y, w, h;
  237. int c, backlightOn, backlightOff;
  238. boolean active;
  239. Module(int x, int y, int w, int h, int c){
  240. this.x = x;
  241. this.y = y;
  242. this.w = w;
  243. this.h = h;
  244. this.c = c;
  245. backlightOn = color(red(c),green(c),blue(c),120);
  246. backlightOff = color(red(c),green(c),blue(c),30);
  247. }
  248. public void draw(){
  249. stroke(c);
  250. strokeWeight(1);
  251. noFill();
  252. noSmooth();
  253. rectMode(CORNER);
  254. rect(x+2,y+2,w-5,h-5);
  255. }
  256. public boolean collision(int cx, int cy){
  257. if(cx > x && cx < x+w && cy > y && cy < y+h){
  258. return true;
  259. }else{
  260. return false;
  261. }
  262. }
  263. public void addCollision(int cursorID, int ax, int ay){ active = true; }
  264. public void updateCollision(int ax, int ay, int bx, int by){}
  265. public void removeCollision(int cursorID){ active = false; }
  266. }
  267. class Monome extends Module{
  268. boolean[] on;
  269. int[] cursors, notes;
  270. int resX,resY;
  271. Monome(int x, int y, int w, int h, int c, int resX, int resY){
  272. super(x,y,w,h,c);
  273. this.resX = resX;
  274. this.resY = resY;
  275. cursors = new int[32];
  276. notes = new int[resX * resY];
  277. for(int i=0; i<(resX * resY); i++){
  278. notes[i] = i;
  279. }
  280. /* String[] noteArray = {
  281. "c#2","d#2","f#2","g#2","a#2",
  282. "c#3","d#3","f#3","g#3","a#3",
  283. "c#4","d#4","f#4","g#4","a#4",
  284. "c#5","d#5","f#5","g#5","a#5",
  285. "c#6","d#6","f#6","g#6","a#6"};
  286. for(int i=0; i<noteArray.length; i++){
  287. int midi = 0;
  288. if(noteArray[i].indexOf('d') != -1)
  289. midi += 2;
  290. if(noteArray[i].indexOf('e') != -1)
  291. midi += 4;
  292. if(noteArray[i].indexOf('f') != -1)
  293. midi += 5;
  294. if(noteArray[i].indexOf('g') != -1)
  295. midi += 7;
  296. if(noteArray[i].indexOf('a') != -1)
  297. midi += 9;
  298. if(noteArray[i].indexOf('b') != -1)
  299. midi += 11;
  300. if(noteArray[i].indexOf('#') != -1)
  301. midi += 1;
  302. int char_to_int = int(map(int(noteArray[i].charAt(noteArray[i].length()-1)),48,58,0,10));
  303. midi += char_to_int * 12;
  304. notes[i] = midi;
  305. }*/
  306. }
  307. public void draw(){
  308. super.draw();
  309. for(int ix=0; ix<resX; ix++){
  310. for(int iy=0; iy<resY; iy++){
  311. fill(round((float)(ix+iy*resX)/(resX*resY)*127));
  312. rect(x + (float)ix/resX * w +2, y + (float)iy/resY * h +2,(w-1)/resX-5,(h-1)/resY-5);
  313. }
  314. }
  315. }
  316. public void addCollision(int cursorID, int ax, int ay){
  317. int xMap = floor(map(ax,x,x+w,0,resX));
  318. int yMap = floor(map(ay,y,y+h,0,resY));
  319. int padID = xMap+yMap*resX;
  320. println("x: " + xMap + " y: " + yMap + " id: " + cursorID);
  321. pressPad(padID);
  322. cursors[cursorID] = padID;
  323. }
  324. public void removeCollision(int cursorID){
  325. releasePad(cursors[cursorID]);
  326. }
  327. public void pressPad(int id){
  328. int send = output.sendNoteOn(0, notes[id], 100);
  329. }
  330. public void releasePad(int id){
  331. int send = output.sendNoteOff(0, notes[id], 100);
  332. }
  333. }
  334. class Slider extends Module{
  335. boolean horizontal, vertical, absolute;
  336. int handle_w, handle_h;
  337. float valueX, valueY;
  338. Slider(int x, int y, int w, int h, int c, String mode, String absolute){
  339. super(x,y,w,h,c);
  340. if(mode.equals("horizontal")){
  341. horizontal = true;
  342. vertical = false;
  343. handle_h = h-3;
  344. handle_w = min(w/6, 15);
  345. valueX = 0.5f;
  346. midi_controller = new int[1];
  347. midi_controller[0] = next_available_midi;
  348. next_available_midi++;
  349. }
  350. if(mode.equals("vertical")){
  351. horizontal = false;
  352. vertical = true;
  353. handle_h = min(h/6, 15);
  354. handle_w = w-3;
  355. valueY = 0.5f;
  356. midi_controller = new int[1];
  357. midi_controller[0] = next_available_midi;
  358. next_available_midi++;
  359. }
  360. if(mode.equals("xy")){
  361. horizontal = true;
  362. vertical = true;
  363. int smaller = min(w,h);
  364. handle_h = min(smaller/6, 16);
  365. handle_w = min(smaller/6, 16);
  366. valueX = 0.5f;
  367. valueY = 0.5f;
  368. midi_controller = new int[2];
  369. midi_controller[0] = next_available_midi;
  370. midi_controller[1] = next_available_midi;
  371. next_available_midi++;
  372. }
  373. if(absolute.equals("absolute")){
  374. this.absolute = true;
  375. }
  376. }
  377. public void draw(){
  378. super.draw();
  379. fill(c);
  380. noStroke();
  381. float xVal = x + w*valueX;
  382. float yVal = y + h*valueY;
  383. if(horizontal && !vertical){
  384. rect(xVal, y+2, handle_w,handle_h);
  385. }
  386. if(vertical && !horizontal){
  387. rect(x+2, yVal, handle_w,handle_h);
  388. }
  389. if(horizontal && vertical){
  390. rectMode(CENTER);
  391. rect(xVal, yVal, handle_w,handle_h);
  392. stroke(c);
  393. line(x,yVal,x+w,yVal);
  394. line(xVal,y,xVal,y+h);
  395. }
  396. }
  397. public void updateCollision(int ax, int ay, int bx, int by){
  398. if(absolute){
  399. if(horizontal){
  400. valueX = (float)(bx-x)/w;
  401. }
  402. if(vertical){
  403. valueY = (float)(by-y)/h;
  404. }
  405. }else{
  406. if(horizontal){
  407. if(valueX >= 0 && valueX <= 1)
  408. valueX += PApplet.parseFloat(bx-ax)/w;
  409. }
  410. if(vertical){
  411. if(valueY >= 0 && valueY <= 1)
  412. valueY += PApplet.parseFloat(by-ay)/h;
  413. }
  414. }
  415. valueX = max(valueX, 0);
  416. valueX = min(valueX, 1);
  417. valueY = max(valueY, 0);
  418. valueY = min(valueY, 1);
  419. if((horizontal && !vertical) || (!horizontal && vertical)){
  420. float value = max(valueX,valueY);
  421. output.sendController(0,midi_controller[0],round(value*127));
  422. }
  423. if(horizontal && vertical){
  424. output.sendController(0,midi_controller[0],round(valueX*127));
  425. output.sendController(0,midi_controller[1],round(valueY*127));
  426. }
  427. }
  428. }
  429. static public void main(String args[]) {
  430. PApplet.main(new String[] { "--present", "--bgcolor=#666666", "--hide-stop", "Lemur3" });
  431. }
  432. }