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);