diff src/melodyTriangle.cpp @ 25:f4ebb87adec1

Added code to keep track of true position of voices in information space; Two voice drawing methods display both true position target position while dragging; string to Voice::status code no longer required; refactored OSC message sending code; added keys to control subdivision ratio for period and shift controls.
author samer
date Sun, 05 Feb 2012 18:13:30 +0000
parents 460c05dd74d0
children 10afc9afb79d
line wrap: on
line diff
--- a/src/melodyTriangle.cpp	Sat Feb 04 23:15:02 2012 +0000
+++ b/src/melodyTriangle.cpp	Sun Feb 05 18:13:30 2012 +0000
@@ -3,10 +3,12 @@
 
 #define BUFFER_ZONE 64 // have to drag this far to snap out of triange.
 
+static int tempi[]={20,30,45,60,90,120,150,180};
+
 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, 
 							   bool enableKeys,int voiceIdOffset,int receivePort): 
 	numVoices(numVoices), enableKeys(enableKeys), receivePort(receivePort),
-	display_msg(""), display_frames(0)
+	display_msg(""), display_frames(0), ratio(2), tempoIndex(4)
 {
 	printf("in constructor: %s %i %i %i %i %i\n",
 		   host,port,numVoices,enableKeys,voiceIdOffset,receivePort);
@@ -35,10 +37,11 @@
 	// isosceles and left-right symmetric around x=x1.
 	// Otherwise the clipping won't work
 	fitTriangleIn(ofGetWidth(),ofGetHeight());
+	send("/tempo",tempi[tempoIndex]);
 	sendCalibrate();
 	sendReplyTo();
 	
-	voiceGrabbed=-1;
+	voiceGrabbed=NULL;
 }
 
 //--------------------------------------------------------------
@@ -53,8 +56,8 @@
 	}
 	
 	constrained=false;
-	if (voiceGrabbed!=-1){
-		Voice *vg=voices[voiceGrabbed];
+	if (voiceGrabbed!=NULL){
+		Voice *vg=voiceGrabbed;
 		if (mouseX!=vg->posx || mouseY!=vg->posy){
 			int clipx=mouseX, clipy=mouseY;
 			bool clipped=clipToTriangle(&clipx,&clipy);
@@ -65,7 +68,7 @@
 					// check how far we clipped
 					if (ofDist(clipx, clipy, mouseX, mouseY) > BUFFER_ZONE) { 
 						// if far enough, we pop out of triangle and send
-						sendDeath(vg->id);
+						send("/death",vg->id);
 						vg->posx=mouseX;
 						vg->posy=mouseY;
 						vg->inTriangle=false;
@@ -84,32 +87,21 @@
 				vg->posx=mouseX;
 				vg->posy=mouseY;
 				if (!clipped){ // ie mouse now in triangle
-					//birth id
-					
-					ofxOscMessage m;
-					m.setAddress( "/birth" );
-					m.addIntArg( vg->id );
-					sender.sendMessage( m );
+					send("/birth",vg->id);
 					
 					printf("sent /birth %i \n",vg->id);
 					sendOctave(vg->id,vg->octave);
 					sendAmplitude(vg->id,vg->amplitude);
 					sendStart=true;
 					vg->inTriangle=true;
+					vg->truex=vg->truey=-1; // ie not known yet.
 				}
 			}
 			
 			if (vg->inTriangle){
 				sendPosition(vg);
 				vg->status=Voice::moved;
-				if (sendStart && vg->isActive){
-					ofxOscMessage m;
-					///track id x y left right top bottom area  
-					m.setAddress( "/start" );
-					m.addIntArg( vg->id );
-					sender.sendMessage( m );
-					printf("sent /start %i \n",vg->id);
-				}
+				if (sendStart && vg->isActive) send("/start",vg->id);
 			}
 		}
 	};
@@ -129,7 +121,7 @@
 	ofNoFill();		
 	ofTriangle(x1, y1, x2, y2, x3, y3);
 	
-	for (int i=0; i<numVoices; i++){
+	for (int i=numVoices-1; i>=0; i--){
 		voices[i]->draw(voices[i]->isInVoice(mouseX,mouseY));
 	}
 	
@@ -141,6 +133,10 @@
 			(ofGetWidth()-bbox.width)/2, (ofGetHeight()-bbox.height)/2);
 		if (display_frames>0) display_frames--;
 	}
+	if (ratio!=2) {
+		ofSetColor(160,160,160);
+		display_font.drawString(ofToString(ratio),16,ofGetHeight()-16);
+	}
 }
 
 bool melodyTriangle::clipToTriangle(int *x, int *y) {
@@ -182,71 +178,59 @@
 
 //- Keyboard ----------------------------------------------------------
 
-void melodyTriangle::keyReleased(int key){}
+void melodyTriangle::keyReleased(int key){
+	if (enableKeys && key>='2' && key<='9') {
+		ratio=2;
+	}
+}
 void melodyTriangle::keyPressed(int key){
-	//printf("key %i",key);
 	if (enableKeys){
-		switch (key) {
-			case ' ': {
-				ofxOscMessage m;
-				m.setAddress( "/marker" );
-				sender.sendMessage(m);
-				printf("sent /marker\n");
-				break;
+		if (key>='2' && key<='9') {
+			ratio=key-'0';
+		} else {
+			printf("got key: %d.\n",key);
+			switch (key) {
+					
+				case '{': 
+					if (tempoIndex>0) tempoIndex--; 
+					send("/tempo",tempi[tempoIndex]); 
+					break;
+				case '}': 
+					if (tempoIndex<7) tempoIndex++;
+					send("/tempo",tempi[tempoIndex]); 
+					break;
+					
+				case ' ': send("/marker"); break;
+				case 'S': send("/save"); break;
+				case 'C': sendReplyTo(); sendCalibrate(); break;
+				case 'F': ofToggleFullscreen(); break;
+				case 'R': reset(); break;
+				case 'Q': ofAppGlutWindow::exitApp();
+
+				default: // otherwise, send key to all voices under mouse
+					for (int i=0; i<numVoices; i++)
+						if (voices[i]->isInVoice(mouseX,mouseY)) 
+							voiceKeypress(voices[i],key);
 			}
-				
-			case '1': case '2':
-			case '3': case '4': {
-				int tempo=30 + 30*(key-'1');
-				ofxOscMessage m;
-				m.setAddress( "/tempo" );
-				m.addIntArg(tempo);
-				sender.sendMessage( m );
-				printf("sent /tempo %d\n",tempo);
-				break;
-			}
-				
-			case 'c': sendReplyTo(); sendCalibrate(); break;
-			case 'F': ofToggleFullscreen(); break;
-			case 'R': reset(); break;
-			case 'Q': ofAppGlutWindow::exitApp();
-
-			default: // otherwise, send key to all voices under mouse
-				for (int i=0; i<numVoices; i++)
-					if (voices[i]->isInVoice(mouseX,mouseY)) 
-						voiceKeypress(voices[i],key);
 		}
-	} else {
-		ofxOscMessage m;
-		m.setAddress( "/key" );
-		m.addIntArg(key);
-		sender.sendMessage(m);
-		printf("sent /key %d\n", key);
-	}
+	} else send("/key",key);
 }
 
 void melodyTriangle::voiceKeypress(Voice *v, int key) {
 	switch (key) {
-		case 'a': {
-			ofxOscMessage m;
-			const char *addr = v->isActive ? "/stop" : "/start";
+		case 'a':
+			send(v->isActive ? "/stop" : "/start", v->id);
 			v->isActive=!v->isActive;
-			m.setAddress(addr);
-			m.addIntArg(v->id );
-			sender.sendMessage( m );
-			printf("sent %s %i \n",addr,v->id);
 			break;
-		}
-		case OF_KEY_LEFT:  sendShift(v->id,-1,2); break;
-		case OF_KEY_RIGHT: sendShift(v->id,1,2); break;
-		case OF_KEY_UP:    sendPeriod(v->id,1,2); break;
-		case OF_KEY_DOWN:  sendPeriod(v->id,2,1); break;
-		case '.': sendPeriod(v->id,1,3); break;
-		case ',': sendPeriod(v->id,3,1); break;
-		case '+': sendOctave(v->id, ++v->octave); break;
-		case '-': sendOctave(v->id, --v->octave); break;
+		case OF_KEY_LEFT:  sendShift(v->id,-1,ratio); break;
+		case OF_KEY_RIGHT: sendShift(v->id,1,ratio); break;
+		case OF_KEY_UP:    sendPeriod(v->id,1,ratio); break;
+		case OF_KEY_DOWN:  sendPeriod(v->id,ratio,1); break;
+		case ']': sendOctave(v->id, ++v->octave); break;
+		case '[': sendOctave(v->id, --v->octave); break;
 		case '*': sendAmplitude(v->id, v->louder()); break;
 		case '/': sendAmplitude(v->id, v->quieter()); break;
+		case 'c': send("/change",v->id); v->status=Voice::pending; break;
 		default:  printf("unrecognised key: %d.\n",key);
 	}
 }
@@ -256,13 +240,25 @@
 void melodyTriangle::mouseDragged(int x, int y, int button){}
 void melodyTriangle::mouseMoved(int x, int y ){}
 void melodyTriangle::mousePressed(int x, int y, int button){
+	// pick up first token under mouse
 	for (int i=0; i<numVoices;i++){
-		if (voices[i]->isInVoice(x,y)) voiceGrabbed=i;
+		if (voices[i]->isInVoice(x,y)) {
+			voiceGrabbed=voices[i];
+			break;
+		}
 	}
 }
 
 void melodyTriangle::mouseReleased(int x, int y, int button){ 
-	voiceGrabbed=-1; 
+	if (voiceGrabbed!=NULL) {
+		Voice *v=voiceGrabbed;
+		if (v->status==Voice::clear) {
+			v->posx=v->truex;
+			v->posy=v->truey;
+			v->truex=v->truey=-1;
+		}
+		voiceGrabbed=NULL; 
+	}
 }
 
 //--------------------------------------------------------------
@@ -274,14 +270,15 @@
 }
 
 void melodyTriangle::reset() {
-	voiceGrabbed=-1;
+	voiceGrabbed=NULL;
 	for (int i=0;i<numVoices;i++) {
 		Voice *v=voices[i];
 		v->posx=x2+RADIUS+(numVoices-1-i)*36;
 		v->posy=48;
 		v->status=Voice::pending;
+		v->isActive=true;
 		if (v->inTriangle) {
-			sendDeath(voices[i]->id);
+			send("/death",voices[i]->id);
 			v->inTriangle=false;
 		}
 	}
@@ -299,19 +296,34 @@
 
 	try {
 		if (msg_path.compare(0,8,"/notify/")==0) {
+			string msg=msg_path.substr(8);
 			Voice *v=get_voice(m.getArgAsInt32(0));
-			if (msg_path=="/notify/status") {
-				v->status=Voice::stringToStatus(m.getArgAsString(1));
-			} else if (msg_path=="/notify/position") {
+			
+			if (msg=="requested") 	 v->status=Voice::waiting;
+			else if (msg=="pending") v->status=Voice::pending;
+			else if (msg=="received") {
+				float x=m.getArgAsFloat(1);
+				float y=m.getArgAsFloat(2);
+				v->status=Voice::clear;
+				if (voiceGrabbed==v) {
+					v->truex=x;
+					v->truey=y;
+				} else {
+					v->posx=x;
+					v->posy=y;
+					v->truex=v->truey=-1;
+				}
+				printf("True position of %d: %4.1f, %4.1f\n",v->id,v->truex,v->truey);
+			} else if (msg=="position") {
 				int x=(int)m.getArgAsFloat(1);
 				int y=(int)m.getArgAsFloat(2);
 				v->posx=x;
 				v->posy=y;
 				v->inTriangle=!clipToTriangle(&x,&y);
-				if (voiceGrabbed==v->id) voiceGrabbed=-1;
-			} else if (msg_path=="/notify/running") {
+				if (voiceGrabbed==v) voiceGrabbed=NULL;
+			} else if (msg=="running") {
 				v->isActive  = m.getArgAsInt32(1) ? true : false;
-			} else if (msg_path=="/notify/params") {
+			} else if (msg=="params") {
 				v->octave    = m.getArgAsInt32(1);
 				v->amplitude = m.getArgAsFloat(2);
 			}
@@ -344,13 +356,6 @@
 
 // OSC Message sending -----------------------------------------
 
-void melodyTriangle::sendDeath(int id) {
-	ofxOscMessage m;
-	m.setAddress( "/death" );	
-	m.addIntArg( id );
-	sender.sendMessage( m );
-}
-
 void melodyTriangle::sendPosition(Voice *v){
 	
 	ofxOscMessage m;
@@ -360,8 +365,7 @@
 	m.addIntArg( v->posx );
 	m.addIntArg( v->posy );
 	sender.sendMessage( m );
-	printf("sent - /track2d %i %i %i\n",v->id,v->posx,v->posy);
-	
+	// printf("sent - /track2d %i %i %i\n",v->id,v->posx,v->posy);
 }
 void melodyTriangle::sendCalibrate(){
 	ofxOscMessage m;
@@ -422,6 +426,20 @@
 	printf("sent /amplitude %i %1.3f\n",id,amp);
 }
 
+void melodyTriangle::send(const char *addr, int a) {
+	ofxOscMessage m;
+	m.setAddress(addr);
+	m.addIntArg(a);
+	sender.sendMessage(m);
+	printf("sent %s %i\n",addr,a);
+}
+
+void melodyTriangle::send(const char *addr) {
+	ofxOscMessage m;
+	m.setAddress(addr);
+	sender.sendMessage(m);
+	printf("sent %s\n",addr);
+}
 
 void melodyTriangle::fitTriangleIn(int width, int height) {
 	int triHeight    = height*0.75;