diff src/melodyTriangle.cpp @ 22:4dcc4312b5fa

Bit of a tidy up, adding text display, added full screen toggle and window resize handler.
author samer
date Thu, 02 Feb 2012 18:17:24 +0000
parents 055d7524bae4
children 460c05dd74d0
line wrap: on
line diff
--- a/src/melodyTriangle.cpp	Wed Feb 01 16:17:32 2012 +0000
+++ b/src/melodyTriangle.cpp	Thu Feb 02 18:17:24 2012 +0000
@@ -12,207 +12,62 @@
  
  
  */
-melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, bool enableKeys,int voiceIdOffset,int receivePort){
+
+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)
+{
 	printf("in constructor: %s %i %i %i %i %i\n",host,port,numVoices,enableKeys,voiceIdOffset,receivePort);
-	this->numVoices=numVoices;
-	this->enableKeys=enableKeys;
-	this->voiceIdOffset=voiceIdOffset;
-	//voices=*Voice[numVoices];
+	for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset);
+	
 	sender.setup( host,port );
 	receiver.setup( receivePort );
-	
-	{
-		ofxOscMessage m;
-		m.setAddress( "/reply_to" );
-		m.addIntArg( receivePort );
-		sender.sendMessage( m );
-		printf("sent /reply_to %i\n",receivePort);
-	}
+	display_font.loadFont("/System/Library/Fonts/HelveticaLight.ttf",32);
 }
 
+melodyTriangle::~melodyTriangle() {
+	printf("Deleting voice objects...\n");
+	for (int i=0;i<numVoices;i++) delete voices[i];
+}
+	
 //--------------------------------------------------------------
 void melodyTriangle::setup(){
-	ofSetCircleResolution(100);
+	ofSetCircleResolution(64);
 	ofBackground(0,0,0);
 	ofSetWindowTitle("Melody Triangle");
+	
 	// if vertical sync is off, we can go a bit fast... 
 	// this caps the framerate at 40fps.
 	ofSetFrameRate(40); 
 	ofEnableSmoothing();
 
+	sendReplyTo();
+	
 	// Set up triange coordinates. 
 	// NB. whatever happens here, the triangle must be
 	// isosceles and left-right symmetric around x=x1.
 	// Otherwise the clipping won't work
-	triangleHeight=ofGetHeight()*0.75;
-	x1=ofGetWidth()/2;
-	y1=(ofGetHeight()-triangleHeight)/2;
-	x2=ofGetWidth()/2-triangleHeight/sqrt(3);
-	y2=ofGetHeight()-(ofGetHeight()-triangleHeight)/2;
-	x3=ofGetWidth()/2+triangleHeight/sqrt(3);
-	y3=y2;
+	fitTriangleIn(ofGetWidth(),ofGetHeight());
+	sendCalibrate();
 	
-	// used for clipping
-	DX13=x3-x1; DY13=y3-y1;
-	SQLEN13=DX13*DX13+DY13*DY13;
-	
-	sendCalibrate();
-	for (int i=0;i<numVoices;i++){
-		voices[i]=new Voice(i+1+voiceIdOffset,x2+15,y1+20+i*30);
-	}
+	for (int i=0;i<numVoices;i++) voices[i]->setPos(x2+voices[i]->radius+i*30,48);
 	voiceGrabbed=-1;
 }
 
-void melodyTriangle::sendCalibrate(){
-	ofxOscMessage m;
-	m.setAddress( "/calibrate" );
-	m.addIntArg( x1 );
-	m.addIntArg( y1 );
-	m.addIntArg( x2 );
-	m.addIntArg( y2 );
-	m.addIntArg( x3 );
-	m.addIntArg( y3 );
-	sender.sendMessage( m );
-	printf("sent /calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3);
-}
-
-void melodyTriangle::sendPeriod(int id, int num, int den){
-	ofxOscMessage m;
-	m.setAddress("/period");
-	m.addIntArg(id);
-	m.addIntArg(num);
-	m.addIntArg(den);
-	sender.sendMessage(m);
-	printf("sent /period %i %i %i\n",id,num,den);
-}
-
-void melodyTriangle::sendShift(int id, int num, int den){
-	ofxOscMessage m;
-	m.setAddress("/shift");
-	m.addIntArg(id);
-	m.addIntArg(num);
-	m.addIntArg(den);
-	sender.sendMessage(m);
-	printf("sent /shift %i %i %i\n",id,num,den);
-}
-
-void melodyTriangle::sendOctave(int id, int oct){
-	ofxOscMessage m;
-	m.setAddress("/octave");
-	m.addIntArg(id);
-	m.addIntArg(oct);
-	sender.sendMessage(m);
-	printf("sent /octave %i %i\n",id,oct);
-}
-
-void melodyTriangle::sendAmplitude(int id, float amp){
-	ofxOscMessage m;
-	m.setAddress("/amplitude");
-	m.addIntArg(id);
-	m.addFloatArg(amp);
-	sender.sendMessage(m);
-	printf("sent /amplitude %i %1.3f\n",id,amp);
-}
-
 //--------------------------------------------------------------
 void melodyTriangle::update(){
-	while( receiver.hasWaitingMessages() )
-	{
+	bool sendStart=false;
+
+	while( receiver.hasWaitingMessages() ) {
 		// get the next message
 		ofxOscMessage m;
 		receiver.getNextMessage( &m );
-		if (m.getAddress()=="/notify") {
-			int id=m.getArgAsInt32(0)-1;
-			string st=m.getArgAsString(1);
-			
-			if (id>=0 && id<numVoices) {
-				Voice *v=voices[id];
-
-				if (st=="received") v->status=Voice::clear;
-				else if (st=="pending") v->status=Voice::pending;
-				else if (st=="requested") v->status=Voice::waiting;
-				else cout << "** unrecognised voice status: " << st << ".\n";
-			} else {
-				cout << "** voice id "<<id<<" out of range.\n";
-			}
-		} else {
-			string msg_string;
-			msg_string = m.getAddress();
-			msg_string += ": ";
-			for ( int i=0; i<m.getNumArgs(); i++ )
-			{
-				// get the argument type
-				msg_string += m.getArgTypeName( i );
-				msg_string += ":";
-				// display the argument - make sure we get the right type
-				if( m.getArgType( i ) == OFXOSC_TYPE_INT32 )
-					msg_string += ofToString( m.getArgAsInt32( i ) );
-				else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
-					msg_string += ofToString( m.getArgAsFloat( i ) );
-				else if( m.getArgType( i ) == OFXOSC_TYPE_STRING )
-					msg_string += m.getArgAsString( i );
-				else
-					msg_string += "unknown";
-			}
-			cout<< msg_string << "\n";
-		}
+		handleMessage(m);
 	}
-}
-
-bool melodyTriangle::clipToTriangle(int *x, int *y) {
-	bool clipped;
 	
-	if (*y>y2) { // off the bottom
-		clipped=true;
-		*y=y2;
-		if (*x<x2) *x=x2; 
-		else if (*x>x3) *x=x3;
-	} else { // have to be a bit cleverer
-		bool reflect=false;
-		if (*x<x1) { // work in reflected coordinates
-			reflect=true;
-			*x=2*x1-*x;
-		}
-		
-		int dx=(*x-x1), dy=(*y-y1); // deltas from top
-		if (dx*DY13 > dy*DX13) {
-			// (x,y) must be somewhere right of triangle now
-			clipped=true;
-			int dp=dx*DX13 + dy*DY13;
-			if (dp<0) { *x=x1; *y=y1; } // off the top
-			else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right
-			else { // project onto right edge
-				*x=x1+dp*DX13/SQLEN13;
-				*y=y1+dp*DY13/SQLEN13;
-			}
-		} else {
-			clipped=false;
-		}
-
-		if (reflect) *x=2*x1 - *x; // reflect back if necessary
-	}
-	return clipped;
-}
-
-
-void melodyTriangle::sendPosition(Voice v){
-	
-	ofxOscMessage m;
-	///track id x y left right top bottom area  
-	m.setAddress( "/track2d" );
-	m.addIntArg( v.id );
-	m.addIntArg( v.posx );
-	m.addIntArg( v.posy );
-	sender.sendMessage( m );
-	printf("sent - /track2d %i %i %i\n",v.id,v.posx,v.posy);
-	
-}
-
-//--------------------------------------------------------------
-void melodyTriangle::draw(){
-	bool constrained=false;
-	bool sendStart=false;
-
+	constrained=false;
 	if (voiceGrabbed!=-1){
 		Voice *vg=voices[voiceGrabbed];
 		if (mouseX!=vg->posx || mouseY!=vg->posy){
@@ -230,7 +85,7 @@
 						m.setAddress( "/death" );
 						m.addIntArg( vg->id );
 						sender.sendMessage( m );
-				
+						
 						printf("sent /death %i \n",vg->id);
 						vg->posx=mouseX;
 						vg->posy=mouseY;
@@ -279,8 +134,12 @@
 			}
 		}
 	};
+}
 
-	//let's draw our triangle
+
+
+//--------------------------------------------------------------
+void melodyTriangle::draw(){
 	ofSetLineWidth(2);
 	ofSetColor(80,80,80);
 	ofFill();		
@@ -295,10 +154,54 @@
 		(*voices[i]).draw();
 	}
 	
-	
+	// display message if any
+	if (display_frames>0) {
+		ofSetColor(220,220,220);
+		display_font.drawString(display_msg,x2,y1+32);
+		display_frames--;
+	}
 }
 
-//--------------------------------------------------------------
+bool melodyTriangle::clipToTriangle(int *x, int *y) {
+	bool clipped;
+	
+	if (*y>y2) { // off the bottom
+		clipped=true;
+		*y=y2;
+		if (*x<x2) *x=x2; 
+		else if (*x>x3) *x=x3;
+	} else { // have to be a bit cleverer
+		bool reflect=false;
+		if (*x<x1) { // work in reflected coordinates
+			reflect=true;
+			*x=2*x1-*x;
+		}
+		
+		int dx=(*x-x1), dy=(*y-y1); // deltas from top
+		if (dx*DY13 > dy*DX13) {
+			// (x,y) must be somewhere right of triangle now
+			clipped=true;
+			int dp=dx*DX13 + dy*DY13;
+			if (dp<0) { *x=x1; *y=y1; } // off the top
+			else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right
+			else { // project onto right edge
+				*x=x1+dp*DX13/SQLEN13;
+				*y=y1+dp*DY13/SQLEN13;
+			}
+		} else {
+			clipped=false;
+		}
+		
+		if (reflect) *x=2*x1 - *x; // reflect back if necessary
+	}
+	return clipped;
+}
+
+
+
+//- Keyboard ----------------------------------------------------------
+
+void melodyTriangle::keyReleased(int key){}
 void melodyTriangle::keyPressed  (int key){
 	//printf("key %i",key);
 	if (enableKeys){
@@ -324,7 +227,8 @@
 			}
 				break;
 				
-			case 'c': sendCalibrate(); break;
+			case 'c': sendReplyTo(); sendCalibrate(); break;
+			case 'f': ofToggleFullscreen(); break;
 
 			default: { // otherwise, send key to all active voices
 				for (int i=0; i<numVoices; i++){
@@ -360,24 +264,15 @@
 	}
 }
 
-//--------------------------------------------------------------
-void melodyTriangle::keyReleased  (int key){
+//- Mouse ------------------------------------------------------
 
-}
-
-//--------------------------------------------------------------
+void melodyTriangle::mouseDragged(int x, int y, int button){}
 void melodyTriangle::mouseMoved(int x, int y ){
 	for (int i=0; i<numVoices;i++){
 		voices[i]->highlight = voices[i]->isInVoice(x,y);
 	}
 }
 
-//--------------------------------------------------------------
-void melodyTriangle::mouseDragged(int x, int y, int button){
-	
-}
-
-//--------------------------------------------------------------
 void melodyTriangle::mousePressed(int x, int y, int button){
 	
 	for (int i=0; i<numVoices;i++){
@@ -390,15 +285,149 @@
 	}
 }
 
-
-
-//--------------------------------------------------------------
-void melodyTriangle::mouseReleased(int x, int y, int button){
-	//printf("released %i",voiceGrabbed);
-	voiceGrabbed=-1;
+void melodyTriangle::mouseReleased(int x, int y, int button){ 
+	voiceGrabbed=-1; 
 }
 
 //--------------------------------------------------------------
+
 void melodyTriangle::windowResized(int w, int h){
+	fitTriangleIn(w,h);
+	sendCalibrate();
+}
 
+
+// OSC Message handling -----------------------------------------
+
+void melodyTriangle::handleMessage(ofxOscMessage &m) {
+	string msg_path=m.getAddress();
+	
+	if (msg_path=="/notify") {
+		int id=m.getArgAsInt32(0)-1;
+		string st=m.getArgAsString(1);
+		
+		if (id>=0 && id<numVoices) {
+			Voice *v=voices[id];
+			
+			if (st=="received") v->status=Voice::clear;
+			else if (st=="pending") v->status=Voice::pending;
+			else if (st=="requested") v->status=Voice::waiting;
+			else cout << "** unrecognised voice status: " << st << ".\n";
+		} else {
+			cout << "** voice id "<<id<<" out of range.\n";
+		}
+	} else if (msg_path=="/display") {
+		display_msg=m.getArgAsString(0);
+		display_frames=m.getArgAsInt32(1);
+		if (display_frames<0) display_frames=0;
+	} else {
+		string msg_string;
+		msg_string = m.getAddress();
+		msg_string += ": ";
+		for ( int i=0; i<m.getNumArgs(); i++ )
+		{
+			// get the argument type
+			msg_string += m.getArgTypeName( i );
+			msg_string += ":";
+			// display the argument - make sure we get the right type
+			if( m.getArgType( i ) == OFXOSC_TYPE_INT32 )
+				msg_string += ofToString( m.getArgAsInt32( i ) );
+			else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
+				msg_string += ofToString( m.getArgAsFloat( i ) );
+			else if( m.getArgType( i ) == OFXOSC_TYPE_STRING )
+				msg_string += m.getArgAsString( i );
+			else
+				msg_string += "unknown";
+		}
+		cout<< msg_string << "\n";
+	}
 }
+
+// OSC Message sending -----------------------------------------
+
+void melodyTriangle::sendPosition(Voice v){
+	
+	ofxOscMessage m;
+	///track id x y left right top bottom area  
+	m.setAddress( "/track2d" );
+	m.addIntArg( v.id );
+	m.addIntArg( v.posx );
+	m.addIntArg( v.posy );
+	sender.sendMessage( m );
+	printf("sent - /track2d %i %i %i\n",v.id,v.posx,v.posy);
+	
+}
+void melodyTriangle::sendCalibrate(){
+	ofxOscMessage m;
+	m.setAddress( "/calibrate" );
+	m.addIntArg( x1 );
+	m.addIntArg( y1 );
+	m.addIntArg( x2 );
+	m.addIntArg( y2 );
+	m.addIntArg( x3 );
+	m.addIntArg( y3 );
+	sender.sendMessage( m );
+	printf("sent /calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3);
+}
+
+void melodyTriangle::sendReplyTo(){	
+	ofxOscMessage m;
+	m.setAddress( "/reply_to" );
+	m.addIntArg( receivePort );
+	sender.sendMessage( m );
+	printf("sent /reply_to %i\n",receivePort);
+}
+
+void melodyTriangle::sendPeriod(int id, int num, int den){
+	ofxOscMessage m;
+	m.setAddress("/period");
+	m.addIntArg(id);
+	m.addIntArg(num);
+	m.addIntArg(den);
+	sender.sendMessage(m);
+	printf("sent /period %i %i %i\n",id,num,den);
+}
+
+void melodyTriangle::sendShift(int id, int num, int den){
+	ofxOscMessage m;
+	m.setAddress("/shift");
+	m.addIntArg(id);
+	m.addIntArg(num);
+	m.addIntArg(den);
+	sender.sendMessage(m);
+	printf("sent /shift %i %i %i\n",id,num,den);
+}
+
+void melodyTriangle::sendOctave(int id, int oct){
+	ofxOscMessage m;
+	m.setAddress("/octave");
+	m.addIntArg(id);
+	m.addIntArg(oct);
+	sender.sendMessage(m);
+	printf("sent /octave %i %i\n",id,oct);
+}
+
+void melodyTriangle::sendAmplitude(int id, float amp){
+	ofxOscMessage m;
+	m.setAddress("/amplitude");
+	m.addIntArg(id);
+	m.addFloatArg(amp);
+	sender.sendMessage(m);
+	printf("sent /amplitude %i %1.3f\n",id,amp);
+}
+
+
+void melodyTriangle::fitTriangleIn(int width, int height) {
+	int triHeight    = height*0.75;
+	int triHalfWidth = triHeight/sqrt(3);
+	
+	x1=width/2;
+	x2=x1-triHalfWidth;
+	x3=x1+triHalfWidth;
+	y1=(height-triHeight)/2;
+	y2=y3=height - (height-triHeight)/2;
+	
+	// used for clipping
+	DX13=x3-x1; DY13=y3-y1;
+	SQLEN13=DX13*DX13+DY13*DY13;
+}