# HG changeset patch # User samer # Date 1328465610 0 # Node ID f4ebb87adec1a6676173e16a3db5e84b073143fb # Parent 328822cd308c8898890d8e136bf1e61027e80d51 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. diff -r 328822cd308c -r f4ebb87adec1 src/Voice.cpp --- a/src/Voice.cpp Sat Feb 04 23:15:02 2012 +0000 +++ b/src/Voice.cpp Sun Feb 05 18:13:30 2012 +0000 @@ -12,53 +12,58 @@ inline static double min(double x,double y) { return (x=0) { + ofSetColor(230,230,230); + ofLine(posx,posy,truex,truey); + // ofNoFill(); ofCircle(truex, truey, RADIUS/2-1); + } + ofSetColor(100*r,60*g,60*b); ofFill(); ofCircle(posx, posy, RADIUS); - //ofNoFill(); - //ofCircle(posx, posy, RADIUS); - - if (highlight) { - ofSetColor(230, 230, 230); + ofNoFill(); + if (highlight) ofSetColor(230, 230, 230); + ofCircle(posx, posy, RADIUS); + +} + +void Voice::draw_alt(bool highlight){ + int r,g,b; + switch (status) { + case clear: r=1; g=1; b=0; break; + default: r=1; g=0; b=0; break; + } + if (isActive) { r=2*r; g=2*g; b=2*b; } + + if (inTriangle && truex>=0) { + ofSetColor(230,230,230); + ofLine(posx,posy,truex,truey); + ofSetColor(100*r,60*g,60*b); + ofFill(); + ofCircle(truex, truey, RADIUS); ofNoFill(); + if (highlight) ofSetColor(230, 230, 230); + ofCircle(truex, truey, RADIUS); + } else { + ofSetColor(100*r,60*g,60*b); + ofFill(); ofCircle(posx, posy, RADIUS); - } else { ofNoFill(); + if (highlight) ofSetColor(230, 230, 230); ofCircle(posx, posy, RADIUS); } } + double Voice::louder() { return amplitude=min(1,amplitude*1.0625); } double Voice::quieter() { return amplitude/=1.0625; } - -enum Voice::status Voice::stringToStatus(string s) throw(bad_status) { - if (s=="received") return clear; - else if (s=="pending") return pending; - else if (s=="requested") return waiting; - else throw bad_status(s); -} - -const char *Voice::bad_status::what() const throw() { - return ("Unrecognised voice status: "+str+".").c_str(); -} - diff -r 328822cd308c -r f4ebb87adec1 src/Voice.h --- a/src/Voice.h Sat Feb 04 23:15:02 2012 +0000 +++ b/src/Voice.h Sun Feb 05 18:13:30 2012 +0000 @@ -20,26 +20,19 @@ moved }; - class bad_status : public std::exception { - string str; - public: - bad_status(string s): str(s) {} - ~bad_status() throw() {} - const char *what() const throw(); - }; - - static status stringToStatus(string str) throw(bad_status); bool isInVoice(int x, int y) { return (ofDist(x, y, posx, posy)<=RADIUS); }; //void setPos(int x, int y) { posx=x; posy=y; status=pending; } double louder(); double quieter(); void draw(bool highlight); + void draw_alt(bool highlight); - int id; - int posx,posy; - bool isActive; - bool inTriangle; - int octave; + int id; + int posx,posy; + bool isActive; + bool inTriangle; + int octave; double amplitude; - enum status status; + enum status status; + float truex, truey; }; diff -r 328822cd308c -r f4ebb87adec1 src/melodyTriangle.cpp --- 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=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; iisInVoice(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; iisInVoice(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; iisInVoice(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;iposx=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; diff -r 328822cd308c -r f4ebb87adec1 src/melodyTriangle.h --- a/src/melodyTriangle.h Sat Feb 04 23:15:02 2012 +0000 +++ b/src/melodyTriangle.h Sun Feb 05 18:13:30 2012 +0000 @@ -34,19 +34,21 @@ // private methods Voice *get_voice(int id) throw(bad_voice_id); + void voiceKeypress(Voice *v, int key); - void voiceKeypress(Voice *v, int key); void sendReplyTo(); void sendCalibrate(); - void sendDeath(int id); void sendPosition(Voice *v); void sendPeriod(int id, int num, int den); void sendShift(int id, int num, int den); void sendOctave(int id, int oct); void sendAmplitude(int id, float amp); + void send(const char *msg); + void send(const char *msg, int a); + void handleMessage(ofxOscMessage &m); + bool clipToTriangle(int *cx, int *cy); void fitTriangleIn(int w, int h); - void handleMessage(ofxOscMessage &m); void reset(); // Immutable after construction and setup @@ -61,10 +63,12 @@ // mutable state Voice *voices[MAX_VOICES]; - int voiceGrabbed; + Voice *voiceGrabbed; bool constrained; bool enableKeys; int display_frames; + int ratio; + int tempoIndex; string display_msg; ofTrueTypeFont display_font; };