comparison src/melodyTriangle.cpp @ 38:330f2746fedd tip

Added keys help in a smaller font; changed loadness keyboard controls.
author samer
date Mon, 27 Feb 2012 20:09:10 +0000
parents 260cc4f4d70a
children
comparison
equal deleted inserted replaced
37:260cc4f4d70a 38:330f2746fedd
1 #include "melodyTriangle.h" 1 #include "melodyTriangle.h"
2 #include <GLUT/GLUT.h> 2 #include <GLUT/GLUT.h>
3 3
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 #define NUMEL(a) sizeof(a)/sizeof(a[0])
6 7
7 static int tempi[]={20,30,45,60,90,120,150,180,240}; 8 static int tempi[]={20,30,45,60,90,120,150,180,240};
8 9
9 static ofxOscBundle& operator<<(ofxOscBundle &bundle, ofxOscMessage msg) { 10 static ofxOscBundle& operator<<(ofxOscBundle &bundle, ofxOscMessage msg) {
10 bundle.addMessage(msg); return bundle; 11 bundle.addMessage(msg); return bundle;
23 24
24 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, 25 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices,
25 bool enableKeys,int voiceIdOffset,int receivePort): 26 bool enableKeys,int voiceIdOffset,int receivePort):
26 numVoices(numVoices), receivePort(receivePort), snapTruePos(enableKeys), 27 numVoices(numVoices), receivePort(receivePort), snapTruePos(enableKeys),
27 enableKeys(enableKeys), randInit(false),allowExit(true), ratio(2), tempoIndex(4), 28 enableKeys(enableKeys), randInit(false),allowExit(true), ratio(2), tempoIndex(4),
28 display_msg(""), display_frames(0) 29 display_msg(""), display_frames(0), display_font(NULL)
29 { 30 {
30 for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset); 31 for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset);
31 32
32 sender.setup( host,port ); 33 sender.setup( host,port );
33 receiver.setup( receivePort ); 34 receiver.setup( receivePort );
34 display_font.loadFont("/System/Library/Fonts/LucidaGrande.ttc",24); 35 main_font.loadFont("/System/Library/Fonts/LucidaGrande.ttc",24);
36 help_font.loadFont("/System/Library/Fonts/Menlo.ttc",16);
37 //help_font.loadFont("/System/Library/Fonts/Courier.dfont",16);
35 } 38 }
36 39
37 melodyTriangle::~melodyTriangle() { 40 melodyTriangle::~melodyTriangle() {
38 printf("Deleting voice objects...\n"); 41 printf("Deleting voice objects...\n");
39 for (int i=0;i<numVoices;i++) delete voices[i]; 42 for (int i=0;i<numVoices;i++) delete voices[i];
147 voices[i]->draw(enableKeys && voices[i]->isInVoice(mouseX,mouseY)); 150 voices[i]->draw(enableKeys && voices[i]->isInVoice(mouseX,mouseY));
148 } 151 }
149 152
150 // display message if any 153 // display message if any
151 if (display_frames!=0) { 154 if (display_frames!=0) {
152 ofRectangle bbox=display_font.getStringBoundingBox(display_msg,0,0); 155 ofRectangle bbox=display_font->getStringBoundingBox(display_msg,0,0);
153 ofSetColor(220,220,220); 156 ofSetColor(220,220,220);
154 display_font.drawString(display_msg, 157 display_font->drawString(display_msg,
155 (ofGetWidth()-bbox.width)/2, (ofGetHeight()-bbox.height)/2); 158 (ofGetWidth()-bbox.width)/2, (ofGetHeight()-bbox.height)/2);
156 if (display_frames>0) display_frames--; 159 if (display_frames>0) display_frames--;
157 } 160 }
158 if (ratio!=2) { 161 if (ratio!=2) {
159 ofSetColor(160,160,160); 162 ofSetColor(160,160,160);
160 display_font.drawString(ofToString(ratio),16,ofGetHeight()-16); 163 display_font->drawString(ofToString(ratio),16,ofGetHeight()-16);
161 } 164 }
162 } 165 }
163 166
164 bool melodyTriangle::clipToTriangle(int *x, int *y) { 167 bool melodyTriangle::clipToTriangle(int *x, int *y) {
165 bool clipped; 168 bool clipped;
203 void melodyTriangle::keyReleased(int key){ 206 void melodyTriangle::keyReleased(int key){
204 if (enableKeys && key>='2' && key<='9') { 207 if (enableKeys && key>='2' && key<='9') {
205 ratio=2; 208 ratio=2;
206 } 209 }
207 } 210 }
211
212 struct command {
213 const char *key;
214 const char *desc;
215 };
216
217 struct command voice_commands[] = {
218 // { "←", "fractional delay" },
219 // { "→", "fractional advance" },
220 // { "↑", "multiply note rate" },
221 // { "↓", "divide note rate" },
222 { "[right]", "fractional delay" },
223 { "[left]", "fractional advance" },
224 { "[up]", "multiply note rate" },
225 { "[down]", "divide note rate" },
226 { "[", "transpose octave down" },
227 { "]", "transpose octave up" },
228 { "{", "quieter" },
229 { "}", "louder" },
230 { "c", "change to nearby pattern" },
231 { "s", "shuffle notes" },
232 { "h", "this help screen" },
233 { "H", "global keys help screen" },
234 };
235
236 struct command global_commands[] = {
237 { "<", "reduce tempo" },
238 { ">", "increase tempo" },
239 { "I", "toggle randomise on birth" },
240 { "S", "save current pattern" },
241 { "C", "calibrate triangle" },
242 { "F", "toggle full screen" },
243 { "R", "reset token positions" },
244 { "Q", "quit" },
245 { "H", "this help screen" },
246 { "h", "token keys help screen" }
247 };
248
208 void melodyTriangle::keyPressed(int key){ 249 void melodyTriangle::keyPressed(int key){
209 if (enableKeys){ 250 if (enableKeys){
210 if (key>='2' && key<='9') { 251 if (key>='2' && key<='9') {
211 ratio=key-'0'; 252 ratio=key-'0';
212 } else { 253 } else {
213 printf("got key: %d.\n",key); 254 printf("got key: %d.\n",key);
214 switch (key) { 255 switch (key) {
215 256
216 case '{': 257 case '<':
217 if (tempoIndex>0) tempoIndex--; 258 if (tempoIndex>0) tempoIndex--;
218 sender << msg("/tempo",tempi[tempoIndex]); 259 sender << msg("/tempo",tempi[tempoIndex]);
219 break; 260 break;
220 case '}': 261 case '>':
221 if (tempoIndex<NUM_TEMPI-1) tempoIndex++; 262 if (tempoIndex<NUM_TEMPI-1) tempoIndex++;
222 sender << msg("/tempo",tempi[tempoIndex]); 263 sender << msg("/tempo",tempi[tempoIndex]);
223 break; 264 break;
224 265
225 case ' ': sender << msg("/marker"); break; 266 case ' ': sender << msg("/marker"); break;
226 case 'S': sender << msg("/save"); break; 267 case 'S': sender << msg("/save"); break;
227 case 'r': sender << msg("/report"); break; 268 case 'r': sender << msg("/report"); break;
228 case 'i': 269 case 'I':
229 randInit ^= true; 270 randInit ^= true;
230 display_msg = (randInit?"randomise on birth":"no randomise on birth"); 271 display_msg = (randInit?"randomise on birth":"no randomise on birth");
272 display_font = &main_font;
231 display_frames = 40; 273 display_frames = 40;
232 break; 274 break;
233 case 'C': { 275 case 'C': {
234 ofxOscBundle bundle; 276 ofxOscBundle bundle;
235 sender << (bundle << msgReplyTo() << msgCalibrate()); 277 sender << (bundle << msgReplyTo() << msgCalibrate());
236 break; 278 break;
237 } 279 }
238 case 'F': ofToggleFullscreen(); break; 280 case 'F': ofToggleFullscreen(); break;
239 case 'R': reset(); break; 281 case 'R': reset(); break;
240 case 'Q': ofAppGlutWindow::exitApp(); 282 case 'Q': ofAppGlutWindow::exitApp();
283 case '/': display_frames=0; break;
284 case 'h':
285 case 'H':
286 case '?':
287 display_frames = -1;
288 display_msg = help_string(key!='h');
289 display_font = &help_font;
290 break;
291
241 case OF_KEY_ESC: setKeyboardEnable(false); break; 292 case OF_KEY_ESC: setKeyboardEnable(false); break;
242 293
243 default: // otherwise, send key to all voices under mouse 294 default: // otherwise, send key to all voices under mouse
244 for (int i=0; i<numVoices; i++) 295 for (int i=0; i<numVoices; i++)
245 if (voices[i]->isInVoice(mouseX,mouseY)) 296 if (voices[i]->isInVoice(mouseX,mouseY))
264 case OF_KEY_RIGHT: sender << msgShift(v->id,1,ratio); break; 315 case OF_KEY_RIGHT: sender << msgShift(v->id,1,ratio); break;
265 case OF_KEY_UP: sender << msgPeriod(v->id,1,ratio); break; 316 case OF_KEY_UP: sender << msgPeriod(v->id,1,ratio); break;
266 case OF_KEY_DOWN: sender << msgPeriod(v->id,ratio,1); break; 317 case OF_KEY_DOWN: sender << msgPeriod(v->id,ratio,1); break;
267 case ']': sender << msgOctave(v->id, ++v->octave); break; 318 case ']': sender << msgOctave(v->id, ++v->octave); break;
268 case '[': sender << msgOctave(v->id, --v->octave); break; 319 case '[': sender << msgOctave(v->id, --v->octave); break;
269 case '*': sender << msgAmplitude(v->id, v->louder()); break; 320 case '}': sender << msgAmplitude(v->id, v->louder()); break;
270 case '/': sender << msgAmplitude(v->id, v->quieter()); break; 321 case '{': sender << msgAmplitude(v->id, v->quieter()); break;
271 case 'c': sender << msg("/change",v->id); v->status=Voice::pending; break; 322 case 'c': sender << msg("/change",v->id); v->status=Voice::pending; break;
323 case 's': sender << msg("/shuffle",v->id); break;
272 default: printf("unrecognised key: %d.\n",key); 324 default: printf("unrecognised key: %d.\n",key);
273 } 325 }
274 } 326 }
327
328 inline int max(int x, int y) { return y>x ? y : x; }
329
330 string melodyTriangle::help_string(bool global) {
331 stringstream buf;
332 struct command *cmds;
333 int n, maxw=0;
334
335 buf << " ( " << (global ? "GLOBAL" : "TOKEN") << " KEYBOARD CONTROLS ) \n\n";
336 if (global) { cmds=global_commands; n=NUMEL(global_commands); }
337 else { cmds=voice_commands; n=NUMEL(voice_commands); }
338
339 for (int i=0; i<n; i++) maxw=max(maxw,strlen(cmds[i].key));
340 for (int i=0; i<n; i++) buf << setw(maxw) << cmds[i].key << " - " << cmds[i].desc << "\n";
341
342 buf << "\nPress '/' to dismiss.";
343 return buf.str();
344 }
345
275 346
276 //- Mouse ------------------------------------------------------ 347 //- Mouse ------------------------------------------------------
277 348
278 void melodyTriangle::mouseDragged(int x, int y, int button){} 349 void melodyTriangle::mouseDragged(int x, int y, int button){}
279 void melodyTriangle::mouseMoved(int x, int y ){} 350 void melodyTriangle::mouseMoved(int x, int y ){}
376 voiceGrabbed=NULL; 447 voiceGrabbed=NULL;
377 } 448 }
378 } else if (msg_path=="/display") { 449 } else if (msg_path=="/display") {
379 display_msg=m.getArgAsString(0); 450 display_msg=m.getArgAsString(0);
380 display_frames=m.getArgAsInt32(1); 451 display_frames=m.getArgAsInt32(1);
452 display_font=&main_font;
381 } else if (msg_path=="/font") { 453 } else if (msg_path=="/font") {
382 display_font.loadFont(m.getArgAsString(0),m.getArgAsInt32(1)); 454 main_font.loadFont(m.getArgAsString(0),m.getArgAsInt32(1));
383 } else if (msg_path=="/keyboard") { setKeyboardEnable(m.getArgAsInt32(0)); } 455 } else if (msg_path=="/keyboard") { setKeyboardEnable(m.getArgAsInt32(0)); }
384 else if (msg_path=="/reset") { reset(); } 456 else if (msg_path=="/reset") { reset(); }
385 else if (msg_path=="/fullscreen") { ofSetFullscreen(m.getArgAsInt32(0)); } 457 else if (msg_path=="/fullscreen") { ofSetFullscreen(m.getArgAsInt32(0)); }
386 else if (msg_path=="/quit") { ofAppGlutWindow::exitApp(); } 458 else if (msg_path=="/quit") { ofAppGlutWindow::exitApp(); }
387 else if (msg_path=="/allowExit") { allowExit=m.getArgAsInt32(0); } 459 else if (msg_path=="/allowExit") { allowExit=m.getArgAsInt32(0); }
406 void melodyTriangle::setKeyboardEnable(bool en) { 478 void melodyTriangle::setKeyboardEnable(bool en) {
407 enableKeys=en; 479 enableKeys=en;
408 snapTruePos=en; 480 snapTruePos=en;
409 display_msg=en ? "Keyboard enabled" : "Keybard disabled"; 481 display_msg=en ? "Keyboard enabled" : "Keybard disabled";
410 display_frames=40; 482 display_frames=40;
483 display_font=&main_font;
411 } 484 }
412 485
413 // OSC Message sending ----------------------------------------- 486 // OSC Message sending -----------------------------------------
414 487
415 ofxOscMessage melodyTriangle::msgPosition(Voice *v){ 488 ofxOscMessage melodyTriangle::msgPosition(Voice *v){