Mercurial > hg > screen-ui
comparison src/melodyTriangle.cpp @ 37:260cc4f4d70a
Now using OSC bundles to make sure cotemporal messages are received in correct order;
also added randInit state flag (toggle 'i') to control sending of /randinit on birth.
author | samer |
---|---|
date | Wed, 22 Feb 2012 00:30:20 +0000 |
parents | 06a2fdb333ca |
children | 330f2746fedd |
comparison
equal
deleted
inserted
replaced
36:f973f0cc743b | 37:260cc4f4d70a |
---|---|
4 #define BUFFER_ZONE 64 // have to drag this far to snap out of triange. | 4 #define BUFFER_ZONE 64 // have to drag this far to snap out of triange. |
5 #define NUM_TEMPI 9 | 5 #define NUM_TEMPI 9 |
6 | 6 |
7 static int tempi[]={20,30,45,60,90,120,150,180,240}; | 7 static int tempi[]={20,30,45,60,90,120,150,180,240}; |
8 | 8 |
9 static ofxOscBundle& operator<<(ofxOscBundle &bundle, ofxOscMessage msg) { | |
10 bundle.addMessage(msg); return bundle; | |
11 } | |
12 | |
13 static ofxOscSender& operator<<(ofxOscSender &sender, ofxOscMessage msg) { | |
14 sender.sendMessage(msg); | |
15 return sender; | |
16 } | |
17 | |
18 static ofxOscSender& operator<<(ofxOscSender &sender, ofxOscBundle bundle) { | |
19 sender.sendBundle(bundle); | |
20 return sender; | |
21 } | |
22 | |
9 | 23 |
10 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, | 24 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, |
11 bool enableKeys,int voiceIdOffset,int receivePort): | 25 bool enableKeys,int voiceIdOffset,int receivePort): |
12 numVoices(numVoices), receivePort(receivePort), snapTruePos(enableKeys), | 26 numVoices(numVoices), receivePort(receivePort), snapTruePos(enableKeys), |
13 enableKeys(enableKeys), allowExit(true), ratio(2), tempoIndex(4), | 27 enableKeys(enableKeys), randInit(false),allowExit(true), ratio(2), tempoIndex(4), |
14 display_msg(""), display_frames(0) | 28 display_msg(""), display_frames(0) |
15 { | 29 { |
16 for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset); | 30 for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset); |
17 | 31 |
18 sender.setup( host,port ); | 32 sender.setup( host,port ); |
36 // Set up triange coordinates. | 50 // Set up triange coordinates. |
37 // NB. whatever happens here, the triangle must be | 51 // NB. whatever happens here, the triangle must be |
38 // isosceles and left-right symmetric around x=x1. | 52 // isosceles and left-right symmetric around x=x1. |
39 // Otherwise the clipping won't work | 53 // Otherwise the clipping won't work |
40 fitTriangleIn(ofGetWidth(),ofGetHeight()); | 54 fitTriangleIn(ofGetWidth(),ofGetHeight()); |
41 send("/tempo",tempi[tempoIndex]); | 55 |
42 sendCalibrate(); | 56 ofxOscBundle bundle; |
43 sendReplyTo(); | 57 sender << ( bundle |
58 << msg("/tempo",tempi[tempoIndex]) | |
59 << msgCalibrate() | |
60 << msgReplyTo()); | |
44 | 61 |
45 voiceGrabbed=NULL; | 62 voiceGrabbed=NULL; |
46 } | 63 } |
47 | 64 |
48 //-------------------------------------------------------------- | 65 //-------------------------------------------------------------- |
60 if (voiceGrabbed!=NULL){ | 77 if (voiceGrabbed!=NULL){ |
61 Voice *vg=voiceGrabbed; | 78 Voice *vg=voiceGrabbed; |
62 if (mouseX!=vg->posx || mouseY!=vg->posy){ | 79 if (mouseX!=vg->posx || mouseY!=vg->posy){ |
63 int clipx=mouseX, clipy=mouseY; | 80 int clipx=mouseX, clipy=mouseY; |
64 bool clipped=clipToTriangle(&clipx,&clipy); | 81 bool clipped=clipToTriangle(&clipx,&clipy); |
82 ofxOscBundle bundle; | |
65 | 83 |
66 if (vg->inTriangle) { | 84 if (vg->inTriangle) { |
67 | 85 |
68 if (clipped) { | 86 if (clipped) { |
69 // check how far we clipped | 87 // check how far we clipped |
70 if (ofDist(clipx, clipy, mouseX, mouseY)>BUFFER_ZONE && allowExit) { | 88 if (ofDist(clipx, clipy, mouseX, mouseY)>BUFFER_ZONE && allowExit) { |
71 // if far enough, we pop out of triangle and send | 89 // if far enough, we pop out of triangle and send |
72 send("/death",vg->id); | 90 bundle << msg("/death",vg->id); |
91 sender << bundle; | |
73 vg->posx=mouseX; | 92 vg->posx=mouseX; |
74 vg->posy=mouseY; | 93 vg->posy=mouseY; |
75 vg->inTriangle=false; | 94 vg->inTriangle=false; |
76 vg->status=Voice::pending; | 95 vg->status=Voice::pending; |
77 } else { | 96 } else { |
86 } | 105 } |
87 } else { // token was outside triangle | 106 } else { // token was outside triangle |
88 vg->posx=mouseX; | 107 vg->posx=mouseX; |
89 vg->posy=mouseY; | 108 vg->posy=mouseY; |
90 if (!clipped){ // ie mouse now in triangle | 109 if (!clipped){ // ie mouse now in triangle |
91 send("/birth",vg->id); | 110 bundle << msg("/birth",vg->id) |
92 | 111 << msgAmplitude(vg->id,vg->amplitude) |
93 printf("sent /birth %i \n",vg->id); | 112 << ( randInit |
94 sendOctave(vg->id,vg->octave); | 113 ? msg("/randinit",vg->id) |
95 sendAmplitude(vg->id,vg->amplitude); | 114 : msgOctave(vg->id,vg->octave) |
115 ); | |
96 sendStart=true; | 116 sendStart=true; |
97 vg->inTriangle=true; | 117 vg->inTriangle=true; |
98 vg->truex=vg->truey=-1; // ie not known yet. | 118 vg->truex=vg->truey=-1; // ie not known yet. |
99 } | 119 } |
100 } | 120 } |
101 | 121 |
102 if (vg->inTriangle){ | 122 if (vg->inTriangle){ |
103 sendPosition(vg); | 123 bundle << msgPosition(vg); |
104 vg->status=Voice::moved; | 124 vg->status=Voice::moved; |
105 if (sendStart && vg->isActive) send("/start",vg->id); | 125 if (sendStart && vg->isActive) bundle << msg("/start",vg->id); |
126 sender << bundle; | |
106 } | 127 } |
107 } | 128 } |
108 }; | 129 }; |
109 } | 130 } |
110 | 131 |
192 printf("got key: %d.\n",key); | 213 printf("got key: %d.\n",key); |
193 switch (key) { | 214 switch (key) { |
194 | 215 |
195 case '{': | 216 case '{': |
196 if (tempoIndex>0) tempoIndex--; | 217 if (tempoIndex>0) tempoIndex--; |
197 send("/tempo",tempi[tempoIndex]); | 218 sender << msg("/tempo",tempi[tempoIndex]); |
198 break; | 219 break; |
199 case '}': | 220 case '}': |
200 if (tempoIndex<NUM_TEMPI-1) tempoIndex++; | 221 if (tempoIndex<NUM_TEMPI-1) tempoIndex++; |
201 send("/tempo",tempi[tempoIndex]); | 222 sender << msg("/tempo",tempi[tempoIndex]); |
202 break; | 223 break; |
203 | 224 |
204 case ' ': send("/marker"); break; | 225 case ' ': sender << msg("/marker"); break; |
205 case 'S': send("/save"); break; | 226 case 'S': sender << msg("/save"); break; |
206 case 'r': send("/report"); break; | 227 case 'r': sender << msg("/report"); break; |
207 case 'C': sendReplyTo(); sendCalibrate(); break; | 228 case 'i': |
229 randInit ^= true; | |
230 display_msg = (randInit?"randomise on birth":"no randomise on birth"); | |
231 display_frames = 40; | |
232 break; | |
233 case 'C': { | |
234 ofxOscBundle bundle; | |
235 sender << (bundle << msgReplyTo() << msgCalibrate()); | |
236 break; | |
237 } | |
208 case 'F': ofToggleFullscreen(); break; | 238 case 'F': ofToggleFullscreen(); break; |
209 case 'R': reset(); break; | 239 case 'R': reset(); break; |
210 case 'Q': ofAppGlutWindow::exitApp(); | 240 case 'Q': ofAppGlutWindow::exitApp(); |
211 case OF_KEY_ESC: setKeyboardEnable(false); break; | 241 case OF_KEY_ESC: setKeyboardEnable(false); break; |
212 | 242 |
216 voiceKeypress(voices[i],key); | 246 voiceKeypress(voices[i],key); |
217 } | 247 } |
218 } | 248 } |
219 } else { | 249 } else { |
220 if (key==OF_KEY_ESC) setKeyboardEnable(true); | 250 if (key==OF_KEY_ESC) setKeyboardEnable(true); |
221 else send("/key",key); | 251 else sender << msg("/key",key); |
222 } | 252 } |
223 } | 253 } |
224 | 254 |
225 void melodyTriangle::voiceKeypress(Voice *v, int key) { | 255 void melodyTriangle::voiceKeypress(Voice *v, int key) { |
226 switch (key) { | 256 switch (key) { |
227 case 'a': | 257 case 'a': |
228 if (v->inTriangle) { | 258 if (v->inTriangle) { |
229 send(v->isActive ? "/stop" : "/start", v->id); | 259 sender << msg(v->isActive ? "/stop" : "/start", v->id); |
230 } | 260 } |
231 v->isActive=!v->isActive; | 261 v->isActive=!v->isActive; |
232 break; | 262 break; |
233 case OF_KEY_LEFT: sendShift(v->id,-1,ratio); break; | 263 case OF_KEY_LEFT: sender << msgShift(v->id,-1,ratio); break; |
234 case OF_KEY_RIGHT: sendShift(v->id,1,ratio); break; | 264 case OF_KEY_RIGHT: sender << msgShift(v->id,1,ratio); break; |
235 case OF_KEY_UP: sendPeriod(v->id,1,ratio); break; | 265 case OF_KEY_UP: sender << msgPeriod(v->id,1,ratio); break; |
236 case OF_KEY_DOWN: sendPeriod(v->id,ratio,1); break; | 266 case OF_KEY_DOWN: sender << msgPeriod(v->id,ratio,1); break; |
237 case ']': sendOctave(v->id, ++v->octave); break; | 267 case ']': sender << msgOctave(v->id, ++v->octave); break; |
238 case '[': sendOctave(v->id, --v->octave); break; | 268 case '[': sender << msgOctave(v->id, --v->octave); break; |
239 case '*': sendAmplitude(v->id, v->louder()); break; | 269 case '*': sender << msgAmplitude(v->id, v->louder()); break; |
240 case '/': sendAmplitude(v->id, v->quieter()); break; | 270 case '/': sender << msgAmplitude(v->id, v->quieter()); break; |
241 case 'c': send("/change",v->id); v->status=Voice::pending; break; | 271 case 'c': sender << msg("/change",v->id); v->status=Voice::pending; break; |
242 default: printf("unrecognised key: %d.\n",key); | 272 default: printf("unrecognised key: %d.\n",key); |
243 } | 273 } |
244 } | 274 } |
245 | 275 |
246 //- Mouse ------------------------------------------------------ | 276 //- Mouse ------------------------------------------------------ |
271 | 301 |
272 //-------------------------------------------------------------- | 302 //-------------------------------------------------------------- |
273 | 303 |
274 void melodyTriangle::windowResized(int w, int h){ | 304 void melodyTriangle::windowResized(int w, int h){ |
275 fitTriangleIn(w,h); | 305 fitTriangleIn(w,h); |
276 sendCalibrate(); | 306 sender << msgCalibrate(); |
277 reset(); | 307 reset(); |
278 } | 308 } |
279 | 309 |
280 void melodyTriangle::reset() { | 310 void melodyTriangle::reset() { |
281 voiceGrabbed=NULL; | 311 voiceGrabbed=NULL; |
284 v->posx=x2+RADIUS+(numVoices-1-i)*36; | 314 v->posx=x2+RADIUS+(numVoices-1-i)*36; |
285 v->posy=48; | 315 v->posy=48; |
286 v->status=Voice::pending; | 316 v->status=Voice::pending; |
287 v->isActive=true; | 317 v->isActive=true; |
288 if (v->inTriangle) { | 318 if (v->inTriangle) { |
289 send("/death",v->id); | 319 sender << msg("/death",v->id); |
290 v->inTriangle=false; | 320 v->inTriangle=false; |
291 } | 321 } |
292 } | 322 } |
293 } | 323 } |
294 | 324 |
380 display_frames=40; | 410 display_frames=40; |
381 } | 411 } |
382 | 412 |
383 // OSC Message sending ----------------------------------------- | 413 // OSC Message sending ----------------------------------------- |
384 | 414 |
385 void melodyTriangle::sendPosition(Voice *v){ | 415 ofxOscMessage melodyTriangle::msgPosition(Voice *v){ |
386 | 416 |
387 ofxOscMessage m; | 417 ofxOscMessage m; |
388 ///track id x y left right top bottom area | 418 ///track id x y left right top bottom area |
389 m.setAddress( "/track2d" ); | 419 m.setAddress( "/track2d" ); |
390 m.addIntArg( v->id ); | 420 m.addIntArg( v->id ); |
391 m.addIntArg( v->posx ); | 421 m.addIntArg( v->posx ); |
392 m.addIntArg( v->posy ); | 422 m.addIntArg( v->posy ); |
393 sender.sendMessage( m ); | 423 // printf("/track2d %i %i %i\n",v->id,v->posx,v->posy); |
394 // printf("sent - /track2d %i %i %i\n",v->id,v->posx,v->posy); | 424 return m; |
395 } | 425 } |
396 void melodyTriangle::sendCalibrate(){ | 426 |
427 ofxOscMessage melodyTriangle::msgCalibrate(){ | |
397 ofxOscMessage m; | 428 ofxOscMessage m; |
398 m.setAddress( "/calibrate" ); | 429 m.setAddress( "/calibrate" ); |
399 m.addIntArg( x1 ); | 430 m.addIntArg( x1 ); |
400 m.addIntArg( y1 ); | 431 m.addIntArg( y1 ); |
401 m.addIntArg( x2 ); | 432 m.addIntArg( x2 ); |
402 m.addIntArg( y2 ); | 433 m.addIntArg( y2 ); |
403 m.addIntArg( x3 ); | 434 m.addIntArg( x3 ); |
404 m.addIntArg( y3 ); | 435 m.addIntArg( y3 ); |
405 sender.sendMessage( m ); | 436 printf("/calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3); |
406 printf("sent /calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3); | 437 return m; |
407 } | 438 } |
408 | 439 |
409 void melodyTriangle::sendReplyTo(){ | 440 ofxOscMessage melodyTriangle::msgReplyTo(){ |
410 ofxOscMessage m; | 441 ofxOscMessage m; |
411 m.setAddress( "/reply_to" ); | 442 m.setAddress( "/reply_to" ); |
412 m.addIntArg( receivePort ); | 443 m.addIntArg( receivePort ); |
413 sender.sendMessage( m ); | |
414 printf("sent /reply_to %i\n",receivePort); | 444 printf("sent /reply_to %i\n",receivePort); |
415 } | 445 return m; |
416 | 446 } |
417 void melodyTriangle::sendPeriod(int id, int num, int den){ send("/period",id,num,den); } | 447 |
418 void melodyTriangle::sendShift(int id, int num, int den) { send("/shift",id,num,den); } | 448 ofxOscMessage melodyTriangle::msgPeriod(int id, int num, int den) { return msg("/period",id,num,den); } |
419 void melodyTriangle::sendOctave(int id, int oct){ send("/octave",id,oct); } | 449 ofxOscMessage melodyTriangle::msgShift(int id, int num, int den) { return msg("/shift",id,num,den); } |
420 | 450 ofxOscMessage melodyTriangle::msgOctave(int id, int oct) { return msg("/octave",id,oct); } |
421 void melodyTriangle::sendAmplitude(int id, float amp){ | 451 |
452 ofxOscMessage melodyTriangle::msgAmplitude(int id, float amp){ | |
422 ofxOscMessage m; | 453 ofxOscMessage m; |
423 m.setAddress("/amplitude"); | 454 m.setAddress("/amplitude"); |
424 m.addIntArg(id); | 455 m.addIntArg(id); |
425 m.addFloatArg(amp); | 456 m.addFloatArg(amp); |
426 sender.sendMessage(m); | 457 printf("/amplitude %i %1.3f\n",id,amp); |
427 printf("sent /amplitude %i %1.3f\n",id,amp); | 458 return m; |
428 } | 459 } |
429 | 460 |
430 void melodyTriangle::send(const char *addr, int a, int b, int c) { | 461 ofxOscMessage melodyTriangle::msg(const char *addr, int a, int b, int c) { |
431 ofxOscMessage m; | 462 ofxOscMessage m; |
432 m.setAddress(addr); | 463 m.setAddress(addr); |
433 m.addIntArg(a); | 464 m.addIntArg(a); |
434 m.addIntArg(b); | 465 m.addIntArg(b); |
435 m.addIntArg(c); | 466 m.addIntArg(c); |
436 sender.sendMessage(m); | 467 printf("%s %i %i %i\n",addr,a,b,c); |
437 printf("sent %s %i\n",addr,a); | 468 return m; |
438 } | 469 } |
439 | 470 |
440 | 471 ofxOscMessage melodyTriangle::msg(const char *addr, int a, int b) { |
441 void melodyTriangle::send(const char *addr, int a, int b) { | |
442 ofxOscMessage m; | 472 ofxOscMessage m; |
443 m.setAddress(addr); | 473 m.setAddress(addr); |
444 m.addIntArg(a); | 474 m.addIntArg(a); |
445 m.addIntArg(b); | 475 m.addIntArg(b); |
446 sender.sendMessage(m); | 476 printf("%s %i %i\n",addr,a,b); |
447 printf("sent %s %i\n",addr,a); | 477 return m; |
448 } | 478 } |
449 | 479 |
450 | 480 ofxOscMessage melodyTriangle::msg(const char *addr, int a) { |
451 void melodyTriangle::send(const char *addr, int a) { | |
452 ofxOscMessage m; | 481 ofxOscMessage m; |
453 m.setAddress(addr); | 482 m.setAddress(addr); |
454 m.addIntArg(a); | 483 m.addIntArg(a); |
455 sender.sendMessage(m); | 484 printf("%s %i\n",addr,a); |
456 printf("sent %s %i\n",addr,a); | 485 return m; |
457 } | 486 } |
458 | 487 |
459 void melodyTriangle::send(const char *addr) { | 488 ofxOscMessage melodyTriangle::msg(const char *addr) { |
460 ofxOscMessage m; | 489 ofxOscMessage m; |
461 m.setAddress(addr); | 490 m.setAddress(addr); |
462 sender.sendMessage(m); | 491 printf("%s\n",addr); |
463 printf("sent %s\n",addr); | 492 return m; |
464 } | 493 } |
465 | 494 |
466 void melodyTriangle::fitTriangleIn(int width, int height) { | 495 void melodyTriangle::fitTriangleIn(int width, int height) { |
467 int triHeight = height*0.75; | 496 int triHeight = height*0.75; |
468 int triHalfWidth = triHeight/sqrt(3); | 497 int triHalfWidth = triHeight/sqrt(3); |