view testApp.mm @ 15:d5758530a039 tip

oF0.84 Retina, and iPhone support
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 12 May 2015 15:48:52 +0100
parents 4ba81a12b008
children
line wrap: on
line source
#include "testApp.h"

/*
 TODO list
 
 video out !!!!!
 
 ios buttons etc
 circular line string with invisible "identify" between two points
 
 symmetry touch mode
 
 new mesh popup menu
 type x,y rings spokes
 
 update to ofx0.8
 
 save presets: 
    create mesh methods: save to json, construct from json
    
    all the stuff in control (and off screen OSC ones) 
    lump positions, constraints
    the scan path
    the touch mode
    the midi hit mode (rewrite this whole thing!)
 
 preset recall list
    
 modulation points:
    make filter
    new touch mode, drop modulation point
    pop up list of destinations (or drag line?)
 
 
 
 new super knobs
 new supermenus
 
 algorithmic scan path
 auto- join up scan path...?
 
 floating scan path, with interpolation
 
 band limited touch points (invisible springs connecting to mesh?)

 iphone
 */
extern GlobalForces globalForces;
extern GlobalUI globalUI;
extern ScanPath scanPath;
extern PresetAlertViewController *presetAlertViewController;
//--------------------------------------------------------------
void testApp::setup(){
    
    theMesh = NULL;
	
	ofxAccelerometer.setup();

    try{
        receiver.setup( INPORT );
        OscOK = true;
    }
    catch (std::runtime_error e){
        cout << "OSC couldn't connect. Exception: " << e.what() << '\n';
        OscOK = false;
    }

    try{
        sender.setup( HOST, OUTPORT );
        OscOK = true;
    }
    catch (std::runtime_error e){
        cout << "OSC couldn't connect. Exception: " << e.what() << '\n';
        OscOK = false;
    }
    
    ofBackground(0, 0, 0);
	ofSetFullscreen(true);
	ofSetFrameRate(60);
    
	timeStep = 1/ofGetFrameRate();
    
	ofEnableSmoothing();
    ofEnableAlphaBlending();
    
   
    
    pitch = 60.0;
    phasorIncr = pitch/SAMPLE_RATE;
    globalForces.gravityAmt = 0.0;
    globalForces.avFilterAmt = 0.01;
    
    initialiseMidi();
    // 
	ofSoundStreamSetup(2,0,this, SAMPLE_RATE,256, 2);

    paused = false;
    audioOn = false;
	drawingOn = true;
    
    audioAccessFlag = false;
    meshConstructionFlag = false;
    
    ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT );
    setupGui();
    
    
    setupMesh();
    scanPath.init();
    
    globalUI.touchMode = globalUI.GRAB;
    scanPath.scanMode = scanPath.DISPLACEMENT;
    globalUI.borderSize = ofGetWidth()/8;
    ofSoundStreamStart();

    paused = false;
    audioOn = true;
    
    //ofxiPhoneExternalDisplay::mirrorOn();
    
    cout << "Width: " << ofGetWidth() << endl;
    cout << "Height: " << ofGetHeight() << endl;
    
    // stupid hack for control vis
    hideControls();
    showControls();
    //[ofxiPhoneGetGLView() updateDimensions];
    
    
}

//--------------------------------------------------------------------------
void testApp::initialiseMidi(){
    
    /////////////////////////
    // MIDI
    
    midiChannel = 7;
	
	// enables the network midi session between iOS and Mac OSX on a
	// local wifi network
	//
	// in ofxMidi: open the input/outport network ports named "Session 1"
	//
	// on OSX: use the Audio MIDI Setup Utility to connect to the iOS device
	//
	ofxMidi::enableNetworking();
	
	// list the number of available input & output ports
	ofxMidiIn::listPorts();
	ofxMidiOut::listPorts();
	
	// create and open input ports
	for(int i = 0; i < ofxMidiIn::getNumPorts(); ++i) {
		
		// new object
		inputs.push_back(new ofxMidiIn);
		
		// set this class to receive incoming midi events
		inputs[i]->addListener(this);
		
		// open input port via port number
		inputs[i]->openPort(i);
	}
	
	// create and open output ports
	for(int i = 0; i < ofxMidiOut::getNumPorts(); ++i) {
		
		// new object
		outputs.push_back(new ofxMidiOut);
		
		// open input port via port number
		outputs[i]->openPort(i);
	}
	
	// set this class to receieve midi device (dis)connection events
	ofxMidi::setConnectionListener(this);
    
    // END MIDI
    
}

//--------------------------------------------------------------
Json::Value testApp::convertToJsonForSaving(){
    Json::Value root;
    
    root["pitch"] = pitch; //

    
    root["globalForces"] = globalForces.convertToJsonForSaving();
    
    root["mesh"] = theMesh->convertToJsonForSaving();
    
    return root;
}
//
//--------------------------------------------------------------
void testApp::showPresetNameDialog(){
    if(!presetAlertViewController.alertShowing){ // this is to stop wierd infinite loop in ios5 (simulator)
        [presetAlertViewController showPresetNamePrompt];
        
    }
    
}
//--------------------------------------------------------------
void testApp::savePreset(const string name  = "default" ){
    static int presetNumber;
    
    presetNumber++;
    Json::Value jpreset = convertToJsonForSaving();
    //save json to file
    string fname = ofxiPhoneGetDocumentsDirectory() + "presetFile";
    
    // write to file

    ofFile logFile(fname,ofFile::WriteOnly);
    logFile << jpreset;
    logFile.close();
}
//--------------------------------------------------------------
Json::Value testApp::loadPresetFile(){
    Json::Value jpreset;
    //save json to file
    string fname = ofxiPhoneGetDocumentsDirectory() + "presetFile";
    
    Json::Value root;
    Json::Reader reader;
    
    /////////////
    // read file
    
    ifstream theFile(fname.c_str());
    stringstream fileText;
    string line;
    if(!theFile){
        cout<<"No preset file found\n";
        return root;
    }else{
        while(theFile){
            theFile >> line;
            // cout << line;  // lots!!!!
            fileText << line;
        }
        theFile.close();
    }
    
    cout << "size of preset JSON string:" << fileText.str().length() << "BYTES \n";
    
    bool parsingSuccessful = reader.parse( fileText.str(), root );
    
    if ( !parsingSuccessful )
    {
        // report to the user the failure and their locations in the document.
        std::cout  << "Failed to parse preset JSON: \n" << reader.getFormattedErrorMessages();
        return root; // will be null
    }
    
    return root;
}
//--------------------------------------------------------------
void testApp::constructPresetFromJson(Json::Value& presetJson){
    
    // construct mesh with right type and size
    // impose saved constraints
    // make saved scanpath
    // recall global settings
    pitch = presetJson["pitch"].asDouble();
    
    theMesh = new Mesh(presetJson["mesh"]);
    
    globalForces.setFromJson(presetJson["globalForces"]);
}
//--------------------------------------------------------------
void testApp::loadPreset(){
    if(audioAccessFlag) return; // or rather wait !
    meshConstructionFlag = TRUE;
    
    deleteMesh();
    
    Json::Value jp = loadPresetFile();
    
    constructPresetFromJson(jp);
    
    // check these stupid tyhings
    numTouches = 0;
    meshConstructionFlag = FALSE;
    paused = false;
    audioOn = true;
    drawingOn = true;
    ofSoundStreamStart();
    
    cout << "PRESET WAS LOADED\n";
    
}
//--------------------------------------------------------------
//--------------------------------------------------------------
// App running stuff
//--------------------------------------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
void testApp::exit(){
	ofSoundStreamClose();
    
    // save everything...

    delete guiL;
    
    if(theMesh != NULL){
        scanPath.clear();
        delete theMesh;
    }
    
}

//--------------------------------------------------------------
void testApp::update(){

	if(!paused){
        if (theMesh != NULL){
            theMesh->update();
        
        }

    }
     handleMessages(); // !?!??   
//    if(ofxiPhoneExternalDisplay::isExternalScreenConnected()){
//        if(!ofxiPhoneExternalDisplay::isMirroring()){
//            ofxiPhoneExternalDisplay::mirrorOn();
//            //printf("turned on Mirroring!\n");
//        }
//    }
    
}

//--------------------------------------------------------------
void testApp::draw(){
	if(drawingOn){
        if(theMesh != NULL)
            theMesh->draw();
	}
    if(controlsShowing){
        drawSidePanels();
    }else{
        if (!controlsShowing) scanPath.draw(); // uncomment if you want to see the output waveform
    }
}
//--------------------------------------------------------------
// background for UI
void testApp::drawSidePanels(){
    ofSetColor(123, 123, 123);
    ofRect(0, 0, globalUI.borderSize, ofGetHeight());
    ofRect(ofGetWidth()-globalUI.borderSize, 0, globalUI.borderSize, ofGetHeight());
}
//--------------------------------------------------------------
void testApp::drawMessages(){
    for ( int i=0; i<NUM_MSG_STRINGS; i++ )
    {
        ofDrawBitmapString( msg_strings[i], 10, 40+15*i );
    }
}

//--------------------------------------------------------------
//--------------------------------------------------------------
//------------------------CHANGING MESH----------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
void testApp::setupMesh(){
    // SET UP THE MESH STRUCTURE
    if(audioAccessFlag) return; // or rather wait !
    meshConstructionFlag = TRUE;
    static int type = 0;
    int numTypes = 8;
    


    
    if(type % numTypes == 0){
        theMesh = new SquareCrossMesh(6,6);
        
    }else if (type % numTypes == 1){
        
        // different for iphone
        if(ofGetWidth() == 480){ //PHONE
            theMesh = new SpiderCrossMesh(60,5);
        }else{  //PAD
            //theMesh = new SpiderCrossMesh(140,5);
            
            theMesh = new SpiderCrossMesh(100,9);
        }
    }else if(type % numTypes ==2){
        
        theMesh = new DropletMesh(2000);
        
    }else if(type % numTypes ==3){
        theMesh = new SquareCrossMesh(28,28);
        
    }else if(type % numTypes ==4){
        
        theMesh = new TriangleMesh(34,34);
    }else if(type % numTypes ==5){
        theMesh = new SpiderCrossMesh(30,30);
        
    }else if(type % numTypes ==6){
        
        theMesh = new DropletMesh(128);
    }else if(type % numTypes ==7){
        
        theMesh = new LineMesh(4000);
    }
    type++;
    //theMesh = new LineMesh(123);
    //theMesh = new GroundedLineMesh(400);
    //theMesh = new TriangleMesh(40,40);
    //theMesh = new LineMesh(100);
    
    // SET CONSTANTS UP FOR MESH
    theMesh->setSpringConstant(0.8);
    theMesh->setMass(1);
    theMesh->setFriction(0.99991);
    
    numTouches = 0;
    meshConstructionFlag = FALSE;
    paused = false;
    audioOn = true;
    drawingOn = true;
    ofSoundStreamStart();
    cout << "MESH SETUP\n";
}
//--------------------------------------------------------------
void testApp::deleteMesh(){
     // TODO - OTHER THREADS FUCK THIS UP
    if(audioAccessFlag) return; // or rather wait !
    //stop everything
    
    scanPath.clear();
    ofSoundStreamStop();
    
    paused = true;
    audioOn = false;
    drawingOn = false;
    
    scanPath.clear();
    // trash it
    delete theMesh;
    theMesh = NULL;
    
    cout << "MESH DELETED\n";
}
//--------------------------------------------------------------
void testApp::regenerateMesh(string meshType, int dim1, int dim2){
    
    // more customisable version of setupMesh()
    if(audioAccessFlag) return; 
    
    if (theMesh != NULL) return;
    
    if (meshType == "LineMesh"){
     
        theMesh = new LineMesh(dim1);
    }else if (meshType == "DropletMesh"){
      
        theMesh = new DropletMesh(dim1);
    }else if (meshType == "SpiderMesh"){
      
        theMesh = new SpiderMesh(dim1,dim2);
    }else if (meshType == "SpiderCrossMesh"){
        
        theMesh = new SpiderCrossMesh(dim1,dim2);
    }else if (meshType == "SquareCrossMesh"){
    
        theMesh = new SquareCrossMesh(dim1,dim2);
    }else if (meshType == "TriangleMesh"){
        
        theMesh = new TriangleMesh(dim1,dim2);
    }else if (meshType == "GroundedLineMesh"){
     
        theMesh = new GroundedLineMesh(dim1);
    }else{
        cout << "OSC message error: unrecognised mesh type" << endl;
        return;
    }
    ofSoundStreamStart();
    drawingOn = true;
    paused = false;
    audioOn = true;
    cout << "MESH REGENERATED\n";

}



//--------------------------------------------------------------
//--------------------------------------------------------------
//------------------------KEYS (OSX)----------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
// all this is now osc messages
void testApp::keyPressed(int key){
    
	if (key == 'p'){
        
		paused = !paused;
	}
	if (key == 's'){
		theMesh->toggleSyrup(true);
	}
	if (key == 'f'){
		theMesh->toggleSpringForces(false);
	}	
	if (key == '='){
		theMesh->increasePropagationSpeed();
	}		
	if (key == '-'){
		theMesh->decreasePropagationSpeed();
	}	
	if (key == 'a'){
        if(audioOn){
            audioOn = false;
        }else{
            audioOn = true;
        }
	}	
	if (key == 'r'){
		theMesh->resetPositions();
        theMesh->resetVelocities();

	}	
	if (key == 'e'){
		theMesh->constrain(.0,.0,Mesh::CONSTRAIN_EDGES);
	}
	if (key == 'c'){
		theMesh->constrain(.0,.0,Mesh::CONSTRAIN_CORNERS);
	}
	if (key == 'u'){
		theMesh->unconstrain();
	}
	if (key == 'l'){
		theMesh->setRestLength();
	}
	if (key == '0'){
		theMesh->zeroRestLength();
	}
	if (key == 'd'){
		drawingOn = !drawingOn;
	}
}

//---------------------------------------------------------------

void testApp::keyReleased(int key){
	if (key == 's'){
		theMesh->toggleSyrup(false);
	}
	if (key == 'f'){
		theMesh->toggleSpringForces(true);
	}	
}



//--------------------------------------------------------------
//--------------------------------------------------------------
//------------------------TOUCH---------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------




void testApp::touchDown(ofTouchEventArgs &touch){
    if(theMesh == NULL) return;
    
	double dax, day;
	// touchDown
    //cout << "touchDown ID: " << touch.id << endl;
    if(globalUI.handleTouchDown(touch.x, touch.y)) return;

    
    addTouch();


	
    dax = (double(touch.x) - globalUI.borderSize)/ofGetHeight();
	day = double(touch.y)/ofGetHeight();
    
    switch (globalUI.touchMode){
        case globalUI.GRAB:
            theMesh->grab(dax,day,touch.id);
            break;
        case globalUI.INSCRIBE_PATH:
            // start a new path, with touch id? ie:polyphonic paths!??!
            break;
        case globalUI.FORCE_FIELD:
            globalForces.createForceTouchPoint(dax,day, touch.id);
            break;
        case globalUI.SPATIAL_HARMONIC:
            // work out 
            theMesh->spatialHarmonic(numTouches, 0);
            break;
        case globalUI.CONSTRAIN:
            theMesh->constrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION);
            break;
        case globalUI.UNCONSTRAIN:
            theMesh->unconstrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION);
            break;
        case globalUI.VIBRATE:
            break;
        default:
            
            break;            
    }

    
}

//--------------------------------------------------------------
void testApp::touchMoved(ofTouchEventArgs &touch){
    if(theMesh == NULL) return;
    if(globalUI.handleTouchMove(touch.x, touch.y)) return;
    //cout << "touchMoved ID: " << touch.id << endl;
    

	double dax, day;
	dax = (double(touch.x) - globalUI.borderSize)/ofGetHeight();
	day = double(touch.y)/ofGetHeight();
    
    
    
    /*
    if(kslider->checkForTouch(touch.x, touch.y)){
        cout << "kslider touched";
       kslider->adjust(touch.x,touch.y);
        return;
    }
     */

    switch (globalUI.touchMode){
        case globalUI.GRAB:
            theMesh->drag(dax,day,touch.id);
            break;
        case globalUI.INSCRIBE_PATH:
            theMesh->inscribeScanPath(dax,day);
            break;
        case globalUI.FORCE_FIELD:
            //theMesh->forceField(dax,day,touch.id);
            
            globalForces.moveForceTouchPoint(dax,day, touch.id);
            break;
        case globalUI.SPATIAL_HARMONIC:
            // makes no sense
            break;
        case globalUI.CONSTRAIN:
            theMesh->constrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION);
            break;
        case globalUI.UNCONSTRAIN:
            theMesh->unconstrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION);
            break;
        case globalUI.VIBRATE:
            break;
        default:
            
            break;            
    }
}

//--------------------------------------------------------------
void testApp::touchUp(ofTouchEventArgs &touch){
    if(theMesh == NULL) return;
    if(globalUI.handleTouchUp(touch.x, touch.y)) return;
    
    
    removeTouch();
    

    switch (globalUI.touchMode){
        case globalUI.GRAB:
            theMesh->unGrab(touch.id);
            break;
        case globalUI.INSCRIBE_PATH:
            theMesh->disconnectDraw();
            break;
        case globalUI.FORCE_FIELD:
            globalForces.removeForceTouchPoint(touch.id);
            break;
        case globalUI.SPATIAL_HARMONIC:
            break;
        case globalUI.CONSTRAIN:
            
            break;
        case globalUI.UNCONSTRAIN:
            
            break;
        case globalUI.VIBRATE:
            break;
        default:
            
            break;            
    }

}

//--------------------------------------------------------------
void testApp::touchDoubleTap(ofTouchEventArgs &touch){
    // pretty much useless.
    /*
    ofxOscMessage m;
    m.setAddress( "/test" );
    m.addIntArg( 1 );
    m.addFloatArg( 3.5f );
    m.addStringArg( "hello" );
    m.addFloatArg( ofGetElapsedTimef() );
    sender.sendMessage( m );
     */
    
    //ofxiPhoneScreenGrab(NULL);  
}


//--------------------------------------------------------------
void testApp::addTouch(){
    numTouches++;
    //cout << "numtouches " << numTouches << endl;
}
//--------------------------------------------------------------
void testApp::removeTouch(){
    numTouches--;
    
}

//--------------------------------------------------------------
//--------------------------------------------------------------
    // MOUSE  - NOT NEEDED FOR IPAD
//--------------------------------------------------------------
//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){
	//cout << "mouse moved " << x << 'y' << y << '\n';
    /*
	double dax, day;
	
	// normalise
	dax = double(x)/ofGetWidth();
	day = double(y)/ofGetHeight();
    
	theMesh->checkHover(dax,day);
    
    */
}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){
	//cout << "mouse DRAGGED " << x << 'y' << y << '\n';
    /*
	double dax, day;
	dax = double(x)/ofGetWidth();
	day = double(y)/ofGetHeight();
	
	if(button == 0){
		if(!paused){
			theMesh->drag(dax,day, 0);
		}else{
			// pause mode - draw a scan path!
			
			theMesh->drawScanPath(dax,day);
			audioOn = false;
		}
	}else if(button == 2){
		
	}
     */
    
}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
    /*
	double dax, day;
	// normalise
	dax = double(x)/ofGetWidth();
	day = double(y)/ofGetHeight();
	
	if(button == 0){
		if(paused){
			// draw a path
			audioOn = false;
			theMesh->deleteScanPath();
		}else{
			theMesh->grab(dax,day, 0);
		}
	}else if(button == 2){
		theMesh->constrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION);
	}else{
		cout << "OTHER BUTTON?\n";
	}
     */
    
    
}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
	/*
	if(button == 0){
		theMesh->unGrab(0);
	}else if(button == 2){
	}else{
		cout << "butt other";
	}
     */
	
}
//--------------------------------------------------------------
//--------------------------------------------------------------
//-------------------------AUDIO-----------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------
void testApp::restartAudioStream(){
    ofSoundStreamStart();
    audioOn = true;
    
}
//--------------------------------------------------------------

void testApp::audioReceived(float * input, int bufferSize, int nChannels){
    
}
//--------------------------------------------------------------
void testApp::audioRequested 	(float * output, int bufferSize, int nChannels){
	float sample;
    static double phasor;

    if(meshConstructionFlag) return;
    // if no mesh , scanpath will still be there, but empty should be fine

    phasorIncr = pitch/SAMPLE_RATE;

	if(audioOn){
        audioAccessFlag = TRUE;
		for (int i = 0; i < bufferSize; i++){

			sample  = float(scanPath.getNextSample(phasor));
            
            // hipass to get rid of DC
            //sample = mydspTools.highpass1(sample);
            sample = mydspTools.butter(sample);
            // clip after volume
            sample = sample*globalForces.volume;
            if (sample >= 1.0){
                sample = 0.999999999;
            }else if (sample <= -1.0){
                sample = -0.999999999;
            }
            
			output[i*nChannels    ] = sample;
			output[i*nChannels + 1] = sample;
            
            phasor += phasorIncr;
            
            if(phasor >= 1.0){
                phasor -= 1.0;
            }
		}
        audioAccessFlag = FALSE;
	}else{
		for (int i = 0; i < bufferSize; i++){
			output[i*nChannels    ] = 0.0;
			output[i*nChannels + 1] = 0.0;
		}
	}
    
    
	
}

//--------------------------------------------------------------
//--------------------------------------------------------------
//-------------------------OSC MSGS--------------------------------
//--------------------------------------------------------------
//--------------------------------------------------------------

void testApp::handleMessages(){
    
	// hide old messages
	for ( int i=0; i<NUM_MSG_STRINGS; i++ )
	{
		if ( timers[i] < ofGetElapsedTimef() )
			msg_strings[i] = "";
	}
    
	// check for waiting messages
	while( receiver.hasWaitingMessages() )
	{
		// get the next message
		ofxOscMessage m;
		receiver.getNextMessage( &m );
        //cout << "OSC message: " << m.getAddress() << endl;
        
        /****************/
        /* REGENERATION OF NEW MESH */
        /****************/
        
        // if the mesh is not there check for regenerate , otherwise ignore everything
        if(theMesh == NULL){
            if ( m.getAddress() == "regenerate" )
            {
                string meshType;
                int dim1, dim2;
                int numArgs = m.getNumArgs();
                cout << "REGEN num args: " << numArgs << endl;
                // we want to do some error checking here
                meshType = m.getArgAsString(0);
                cout << "REGEN meshType: " << meshType << endl;
                dim1 = m.getArgAsInt32(1);
                if(numArgs == 3){
                    dim2 = m.getArgAsInt32(2);
                }else{
                    dim2 = 3;
                }
                
                regenerateMesh(meshType,dim1,dim2);

                
            }else{
                return;
            }
        }
        else if ( m.getAddress() == "restartNewMesh" )
		{
            ofSoundStreamStart();
            drawingOn = true;
            paused = false;
            audioOn = true;
            
		}   
        /****************/
        /* NOTE HANDLER */
        /****************/
        
		else if ( m.getAddress() == "note" )
		{
            int note = m.getArgAsInt32(0);
        
            int velocity = m.getArgAsInt32(1);
            if(velocity > 0){
                cout << "note pitch = " << pitch << endl;
                pitch = 440.0/pow(2.0,((69.0 - double(note))/12.0));
                theMesh->hit(0.5,0.5,velocity,globalForces.excitationType,globalForces.excitationShape);
            }else{
                theMesh->damp();
            }
            
            
 		}
        else if ( m.getAddress() == "excitationStrength" )
		{
            globalForces.excitationStrength = m.getArgAsFloat(0);
            
            
 		}
        
        else if ( m.getAddress() == "excitationType" )
		{
            
            // set MIDI twanger mode
            if(m.getArgAsString(0) == "POSITION"){
                globalForces.excitationType = GlobalForces::POSITION;
                
            }else if (m.getArgAsString(0) == "VELOCITY"){
                cout << "excitationType = VELOCITY" << endl;
                globalForces.excitationType = GlobalForces::VELOCITY;
            }
		}
        else if ( m.getAddress() == "excitationShape" )
		{
            
            // set MIDI twanger twang shape
            if(m.getArgAsString(0) == "NOISE"){
                globalForces.excitationShape = GlobalForces::NOISE;
                
            }else if (m.getArgAsString(0) == "GAUSS"){
                cout << "excitationType = GAUSS" << endl;
                globalForces.excitationShape = GlobalForces::GAUSS;
            }else if (m.getArgAsString(0) == "SINE"){
                cout << "excitationType = SINE" << endl;
                globalForces.excitationShape = GlobalForces::SINE;
        
            }
            // set size
            globalForces.exciteShapeX = m.getArgAsInt32(1);
            globalForces.exciteShapeY = m.getArgAsInt32(2);
		}
          
        // touchModes: {GRAB,FORCE_FIELD,SPATIAL_HARMONIC,CONSTRAIN,VIBRATE,INSCRIBE_PATH};
		else if ( m.getAddress() == "touchMode" )
		{
            
            // set touch mode
            if(m.getArgAsString(0) == "GRAB"){
                globalUI.touchMode = globalUI.GRAB;
                
            }else if (m.getArgAsString(0) == "FORCE_FIELD"){
                cout << "touchMode = FORCE_FIELD" << endl;
                globalUI.touchMode = globalUI.FORCE_FIELD;
            }else if (m.getArgAsString(0) == "SPATIAL_HARMONIC"){
                //cout << "touchMode = SPATIAL_HARMONIC" << endl;
                globalUI.touchMode = globalUI.SPATIAL_HARMONIC;
            }else if (m.getArgAsString(0) == "CONSTRAIN"){
                //cout << "touchMode = CONSTRAIN" << endl;
                globalUI.touchMode = globalUI.CONSTRAIN;
            }else if (m.getArgAsString(0) == "VIBRATE"){
                //cout << "touchMode = VIBRATE" << endl;
                globalUI.touchMode = globalUI.VIBRATE;
            }else if (m.getArgAsString(0) == "UNCONSTRAIN"){
                //cout << "touchMode = UNCONSTRAIN" << endl;
                globalUI.touchMode = globalUI.UNCONSTRAIN;
            }else if (m.getArgAsString(0) == "INSCRIBE_PATH"){
                //cout << "touchMode = INSCRIBE_PATH" << endl;
                globalUI.touchMode = globalUI.INSCRIBE_PATH;
                theMesh->clearScanPath();              
            }
		}
       
        else if ( m.getAddress() == "pause" )
		{
            paused = !paused;
		}
        else if ( m.getAddress() == "touchStrength" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    cout << "touchStrength = " << m.getArgAsFloat(i) << endl;
                    
                    globalForces.touchStrength = m.getArgAsFloat(i);
                    globalForces.excitationStrength = globalForces.touchStrength;
                }
            }
		}
        else if ( m.getAddress() == "homingAmt" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    globalForces.homingAmt = m.getArgAsFloat(i);
                }
            }
		}
        else if ( m.getAddress() == "avFilterAmt" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    globalForces.avFilterAmt = m.getArgAsFloat(i);
                }
            }
		}
        else if ( m.getAddress() == "scanMode" )
		{
            // set scan mode
            if (m.getArgAsString(0) == "DISPLACEMENT"){
                cout << "touchMode = DISPLACEMENT" << endl;
                scanPath.scanMode = scanPath.DISPLACEMENT;
            }else if (m.getArgAsString(0) == "SPEED"){
                
                cout << "scanMode = SPEED" << endl;
                scanPath.scanMode = scanPath.SPEED;
            }else if (m.getArgAsString(0) == "SPRING_FORCE"){
                cout << "scanMode = SPRING_FORCE" << endl;
                scanPath.scanMode = scanPath.SPRING_FORCE;
            }else if (m.getArgAsString(0) == "YPOS"){
                cout << "scanMode = YPOS" << endl;
                scanPath.scanMode = scanPath.YPOS;
            }else if (m.getArgAsString(0) == "OTHER"){
                cout << "scanMode = OTHER" << endl;
                //scanMode = OTHER;
            }
		}
		else if ( m.getAddress() == "inscribeScanPath" )
		{
            if (globalUI.touchMode != globalUI.INSCRIBE_PATH){
                theMesh->resetPositions();
                theMesh->resetVelocities();
                paused = true;
                audioOn = false;
                globalUI.touchMode = globalUI.INSCRIBE_PATH;
                theMesh->clearScanPath();
                theMesh->update();
            }else{

                paused = false;
                audioOn = true;
                globalUI.touchMode = globalUI.GRAB;           
            }
            
		}
		else if ( m.getAddress() == "clearScanPath" )
		{
            theMesh->clearScanPath();
		}
        else if ( m.getAddress() == "toggleForce" )
		{
            theMesh->toggleSpringForces();
		}
        else if ( m.getAddress() == "toggleGravity" )
		{
            theMesh->toggleGravity();
		}
        else if ( m.getAddress() == "resetPositions" )
		{
            theMesh->resetPositions();
		}
        else if ( m.getAddress() == "resetVelocities" )
		{
            theMesh->resetVelocities();
		}

        
        else if ( m.getAddress() == "reset" )
		{
            theMesh->resetPositions();
            theMesh->resetVelocities();
            theMesh->update(); 
            
		}
        else if ( m.getAddress() == "deleteMesh" )
		{
            deleteMesh();
		}
        else if ( m.getAddress() == "regenerate" )
		{
            // ignore it - the mesh is not deleted
            
            
		}
        else if ( m.getAddress() == "zeroRestLength" )
		{
            theMesh->zeroRestLength();
		}
        else if ( m.getAddress() == "setThisRestLength" )
		{
            theMesh->setRestLength();
		}
        else if ( m.getAddress() == "setZeroAudioLine" )
		{
            theMesh->setZeroAudioLine();
		}
        else if ( m.getAddress() == "speedLimit" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    globalForces.speedLimit = m.getArgAsFloat(i);
                }
            }
		}
        else if ( m.getAddress() == "gravityAmt" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    globalForces.gravityAmt = m.getArgAsFloat(i);
                }
            }
		}
        else if ( m.getAddress() == "pressureAmt" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    globalForces.pressureAmt = m.getArgAsFloat(i);
                }
            }
		}    
        else if ( m.getAddress() == "wallBounce" )
		{
            for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){
                    //params::wallBounce = m.getArgAsFloat(i);
                }
            }
		}
        else if ( m.getAddress() == "toggleSyrup" )
		{
            theMesh->toggleSyrup();
        }
        else if ( m.getAddress() == "toggleAudio" )
		{
            if(audioOn){
                ofSoundStreamStop();
                audioOn = false;
            }else{
                restartAudioStream();
            }
        
		}       

        else if ( m.getAddress() == "constrainEdges" )
		{
            theMesh->constrain(.0,.0,Mesh::CONSTRAIN_EDGES);
		}
        else if ( m.getAddress() == "constrainCorners" )
		{
            theMesh->constrain(.0,.0,Mesh::CONSTRAIN_CORNERS    );
		}
        else if ( m.getAddress() == "unconstrain" )
        {
            theMesh->unconstrain();
        }
		else if ( m.getAddress() == "mass" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ){
                    theMesh->setMass(m.getArgAsInt32( i ));
                }
                else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    theMesh->setMass(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); 
                }
                
            }
		}
		else if ( m.getAddress() == "springk" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ){
                    theMesh->setSpringConstant(m.getArgAsInt32( i ));
                }
                else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    theMesh->setSpringConstant(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); 
                }
                
            }
		}
		else if ( m.getAddress() == "friction" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ){
                    theMesh->setFriction(m.getArgAsInt32( i ));
                }
                else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    theMesh->setFriction(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); 
                }
                
            }
		}
        //////////////// asym
        else if ( m.getAddress() == "massAsym" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    theMesh->setMassAsym(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); 
                }
                
            }
		}
		else if ( m.getAddress() == "springkAsym" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    theMesh->setSpringConstantAsym(m.getArgAsFloat( i )<0.00?0.00:m.getArgAsFloat( i ) ); 
                }
                
            }
		}
		else if ( m.getAddress() == "frictionAsym" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    theMesh->setFrictionAsym(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); 
                }
                
            }
		}
        else if ( m.getAddress() == "volume" )
		{
			for ( int i=0; i<m.getNumArgs(); i++ )
			{
                if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
                {
                    cout << "change volume\n";
                    globalForces.volume = m.getArgAsFloat( i ); 
                }
                
            }
		}
        ///////////////////////
		else
		{
			// unrecognized message: display on the bottom of the screen
			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 )
                    pitch = 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";
			}
			// add to the list of strings to display
			msg_strings[current_msg_string] = msg_string;
			timers[current_msg_string] = ofGetElapsedTimef() + 5.0f;
			current_msg_string = ( current_msg_string + 1 ) % NUM_MSG_STRINGS;
			// clear the next line
			msg_strings[current_msg_string] = "";
		}
        
	}
}

//--------------------------------------------------------------
//--------------------------------------------------------------
// GUI stuff
//--------------------------------------------------------------
//--------------------------------------------------------------
void testApp::loadLogXML(){
    ofxXmlSettings XMLlog;
    
    string message;
    if( XMLlog.loadFile(ofxiPhoneGetDocumentsDirectory() + "wabletlogs.xml") ){
        message = "mySettings.xml loaded from documents folder!";
        
    }else if( XMLlog.loadFile("Logs/wabletlogs.xml") ){
        message = "mySettings.xml loaded from data folder!";
        
        
    }else{
        message = "unable to load mySettings.xml check data/ folder";
        return;
    }
    cout << message << "\n";
    
    // get all the values from log
    timesOpened = XMLlog.getValue("wabletlogs:timesOpened", 0);
    timesOpened++;
    
}
//--------------------------------------------------------------
void testApp::saveLogXML(){
    ofxXmlSettings XMLlog;
    
    XMLlog.setValue("wabletlogs:timesOpened", timesOpened);
    
    if(XMLlog.saveFile(ofxiPhoneGetDocumentsDirectory() + "wabletlogs.xml")){
        cout << "Saved wabletlogs.XML in iphone documents OK";
    }else if(XMLlog.saveFile("Logs/wabletlogs.xml")){
        cout << "Saved wabletlogs.XML in data folder";
    }else{
        cout << "wabletlogs file did not save :(";
    }
    
    
    
}
//--------------------------------------------------------------
void testApp::setupGui(){
    float xInit = OFX_UI_GLOBAL_WIDGET_SPACING;
    
    int heightS = ofGetHeight();
    int widthS = ofGetWidth();
    
    float sidebarWidth = widthS/8;
    float length = sidebarWidth-xInit*2;
    
    
    float widgetHeight = heightS/18;
    
    /*
    setWidgetColor(OFX_UI_WIDGET_COLOR_BACK, cb);
    setWidgetColor(OFX_UI_WIDGET_COLOR_OUTLINE, co);
    setWidgetColor(OFX_UI_WIDGET_COLOR_OUTLINE_HIGHLIGHT, coh);
    setWidgetColor(OFX_UI_WIDGET_COLOR_FILL, cf);
    setWidgetColor(OFX_UI_WIDGET_COLOR_FILL_HIGHLIGHT, cfh);
    setWidgetColor(OFX_UI_WIDGET_COLOR_PADDED, cp);
    setWidgetColor(OFX_UI_WIDGET_COLOR_PADDED_OUTLINE, cpo);
    */
    
    ofColor bgCol = ofColor(23,23,23);
    ofColor paddingCol = ofColor(56,56,56);
    ofColor padOutlineCol = ofColor(200,0,0);
    ofColor fillCol = ofColor(0,0,205);
    ofColor fillHicol = ofColor(0,0,255);
    ofColor outlineCol = ofColor(255,255,255);
    ofColor outlineHiCol = ofColor(255,255,255);
    // LEFT GUI ------------------
    
    
    guiL = new ofxUICanvas(0,0,sidebarWidth,heightS);
    guiL->addSpacer(length-xInit, 2);
    //guiL->setUIColors(bgCol, outlineCol, outlineHiCol, fillCol, fillHicol, paddingCol, padOutlineCol);
    
    
    guiL->addWidgetDown(new ofxUILabel("Physics", OFX_UI_FONT_LARGE));
    
    ofxUIWidget *slider;
    //ofxUISlider_<<#typename T#>>(<#string _name#>, <#T _min#>, <#T _max#>, <#T _value#>, <#float w#>, <#float h#>)
    slider = guiL->addWidgetDown(new ofxUISlider("SPRING K",0.0,0.8,0.4,length,widgetHeight));
    slider->setDrawPadding(true);
    slider->setDrawPaddingOutline(true);
    slider->setColorFill(fillHicol);
    slider->setColorFillHighlight(fillHicol);
    
    slider = guiL->addWidgetDown(new ofxUISlider("GRAVITY", 0.0, 4.0, 0.0,length,widgetHeight ));
    slider->setDrawPadding(true);
    slider->setDrawPaddingOutline(true);
    slider->setColorFill(fillHicol);
    slider->setColorFillHighlight(fillHicol);

    slider = guiL->addWidgetDown(new ofxUISlider("HOMING",0.0,0.3,0.0,length,widgetHeight));
    slider->setDrawPadding(true);
    slider->setDrawPaddingOutline(true);
    slider->setColorFill(fillHicol);
    slider->setColorFillHighlight(fillHicol);

    slider = guiL->addWidgetDown(new ofxUISlider("SMOOTHING", 0.0, 0.5, 0.01,length,widgetHeight));
    slider->setDrawPadding(true);
    slider->setDrawPaddingOutline(true);
    slider->setColorFill(fillHicol);
    slider->setColorFillHighlight(fillHicol);
    
    
    guiL->addSpacer(length-xInit, 2);

    
    //guiL->setWidgetPosition(OFX_UI_WIDGET_POSITION_DOWN);
	slider = guiL->addSlider("PITCH", 2.0, 100.0, 80.0, length, heightS/2);
    slider->setDrawPadding(true);
    slider->setDrawPaddingOutline(true);
    slider->setColorFill(fillHicol);
    slider->setColorFillHighlight(fillHicol);

    ofAddListener(guiL->newGUIEvent, this, &testApp::guiLEvent);
    
    //guiL->setUIColors( ofColor(56,56,56), ofColor(255,255,56), ofColor(255,255,56), ofColor(0,0,255), ofColor(0,0,255), ofColor(0,0,255), ofColor(0,0,255) );
     // RIGHT GUI -----------------------
    
    guiR = new ofxUICanvas(ofGetWidth()-sidebarWidth, 0, sidebarWidth, ofGetHeight()-64);
    
    
    guiR->addSpacer(length-xInit, 2);
    
    vector<string> names;
	names.push_back("GRAB");
	names.push_back("FORCE");
    names.push_back("SINE");
	names.push_back("STICK");
    names.push_back("UNSTICK");
    names.push_back("NEWPATH");
    
    
    ofxUIRadio* radio;
    radio = guiR->addRadio("TOUCH MODE", names, OFX_UI_ORIENTATION_VERTICAL, widgetHeight, widgetHeight);
    radio->setDrawPadding(true);
    radio->setColorFill(fillHicol);
    radio->setColorFillHighlight(fillHicol);
    
    slider = guiR->addWidgetDown(new ofxUISlider( "TOUCH AMT", -0.4, 4.0, 1.0,length,widgetHeight));
    slider->setDrawPadding(true);
    slider->setColorFill(fillHicol);
    slider->setColorFillHighlight(fillHicol);
    
    guiR->addSpacer(length-xInit, 2);
    
    guiR->addToggle("PAUSE", false, widgetHeight, widgetHeight);
    guiR->addButton("RESET", false, widgetHeight, widgetHeight);
    guiR->addButton("NEW", false, widgetHeight, widgetHeight);
    guiR->addButton("SAVE", false, widgetHeight, widgetHeight);
    guiR->addButton("LOAD", false, widgetHeight, widgetHeight);
    
    ofAddListener(guiR->newGUIEvent, this, &testApp::guiREvent);
    //guiR->loadSettings(ofxiPhoneGetDocumentsDirectory() + "guiSettings.xml");
    radio->activateToggle("GRAB");
    
    // show hide ctrls
    guiSH = new ofxUICanvas(ofGetWidth() - sidebarWidth, ofGetHeight()-64, sidebarWidth, 64);
    
    
    guiSH->addSpacer(length-xInit, 2);
    ofxUIToggle* t = guiSH->addToggle("CTRLS", false, widgetHeight, widgetHeight);
    // turn toggle on
    t->setState(true);
    
    ofAddListener(guiSH->newGUIEvent, this, &testApp::guiSHEvent);
    
}
//--------------------------------------------------------------
void testApp::UIcallBack(int buttID){
    cout << " BUTT ID " << buttID << "\n";
    
}
void testApp::hideControls(){
    cout << "CTRLS ooff";
    guiR->setVisible(false);
    guiL->setVisible(false);
    controlsShowing = false;
}
void testApp::showControls(){
    cout << "CTRLS onnn";
    guiR->setVisible(true);
    guiL->setVisible(true);
    controlsShowing = true;
}
//--------------------------------------------------------------
void testApp::guiSHEvent(ofxUIEventArgs &e)
{
    if(e.widget->getName() == "CTRLS"){
        // ????
        
        cout << ((ofxUIButton *)e.widget)->getValue();
        
        if( ((ofxUIButton *)e.widget)->getValue() == 0) {
            hideControls();
        }else{
            showControls();
        }
        
    }
}

//--------------------------------------------------------------
void testApp::guiREvent(ofxUIEventArgs &e)
{
    if(e.widget->getName() == "TOUCH MODE")
    {
        cout << "TOUCH MODE";
        
    }
    if(e.widget->getName() == "GRAB"){
        cout << "GRAB";
        globalUI.touchMode = globalUI.GRAB;
    }else if(e.widget->getName() == "FORCE"){
        
        globalUI.touchMode = globalUI.FORCE_FIELD;
    }else if(e.widget->getName() == "STICK"){
        
        globalUI.touchMode = globalUI.CONSTRAIN;
    }else if(e.widget->getName() == "UNSTICK"){
        
        globalUI.touchMode = globalUI.UNCONSTRAIN;
    }else if(e.widget->getName() == "NEWPATH"){
        if(globalUI.touchMode != globalUI.INSCRIBE_PATH){
            theMesh->resetPositions();
            theMesh->resetVelocities();
            globalUI.touchMode = globalUI.INSCRIBE_PATH;
            theMesh->clearScanPath();
            theMesh->update();
        }
    }else if(e.widget->getName() == "SINE"){
        globalUI.touchMode = globalUI.SPATIAL_HARMONIC;
    }else if(e.widget->getName() == "RESET"){
        theMesh->resetAll();
        numTouches = 0;
    }else if(e.widget->getName() == "NEW"){
        // ????
        
        cout << ((ofxUIButton *)e.widget)->getValue();
        
        if( ((ofxUIButton *)e.widget)->getValue() == 0) {
            
            deleteMesh();
            setupMesh();
        }else{
            
        }
    }else if(e.widget->getName() == "SAVE"){
        // save the preset somehow
        if( ((ofxUIButton *)e.widget)->getValue() == 0) {
            savePreset();
        }
    }else if(e.widget->getName() == "LOAD"){
        // save the preset somehow
        if( ((ofxUIButton *)e.widget)->getValue() == 0) {
            loadPreset();
        }
    }else if(e.widget->getName() == "PAUSE"){
        paused = !paused;
    }else if(e.widget->getName() == "TOUCH AMT"){
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        slider->setDrawPadding(true);
        globalForces.touchStrength = slider->getScaledValue();
    }
    
}
//--------------------------------------------------------------
void testApp::guiLEvent(ofxUIEventArgs &e)
{
    if(e.widget->getName() == "SPRING K")
    {
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        
        theMesh->setSpringConstant( slider->getScaledValue() );
    }else if(e.widget->getName() == "GRAVITY")
    {
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        slider->setDrawPadding(true);
        globalForces.gravityAmt = slider->getScaledValue();
        //radio->getScaledValue() );
    }else if(e.widget->getName() == "HOMING")
    {
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        globalForces.homingAmt = slider->getScaledValue();
        //radio->getScaledValue() );
    }else if(e.widget->getName() == "SMOOTHING")
    {
        
        
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        globalForces.avFilterAmt = slider->getScaledValue();
        //radio->getScaledValue() );
    }else if(e.widget->getName() == "FRICTION")
    {
        
        
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        theMesh->setFriction(slider->getScaledValue());
        //radio->getScaledValue() );
    }else if(e.widget->getName() == "PITCH")
    {
        
        
        ofxUISlider *slider = (ofxUISlider *) e.widget;
        pitch = slider->getScaledValue();
        //radio->getScaledValue() );
    }
    
    
}

//--------------------------------------------------------------

void testApp::deviceOrientationChanged(int newOrientation){
    
     cout << "orientation: " << newOrientation;
    
     if(newOrientation == 4){
     ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT );
     
     }
     
}


//-------------------------------------------------------------------------
//--------------------------------------------------------------

#pragma mark MIDI
void testApp::addMessage(string msg) {
	cout << msg << endl;
	messages.push_back(msg);
	while(messages.size() > maxMessages)
		messages.pop_front();
}

//--------------------------------------------------------------
void testApp::newMidiMessage(ofxMidiMessage& msg) {
	// recieved one
    static int p; // remembers last note on
    int v;
    // look at what it is
    
    if(msg.status == MIDI_CONTROL_CHANGE){
        int ctl_num = msg.control;
        int ctl_val = msg.value;
        // TODO route control change message here
    }
    
    if(msg.status == MIDI_NOTE_ON){
        p = msg.pitch;
        v = msg.velocity;

        // TODO handle note on here
        if(v > 0){
            //cout << "note pitch = " << p << endl;
            pitch = 440.0/pow(2.0,((69.0 - double(p))/12.0));
            globalForces.excitationShape = GlobalForces::SINE;
            if(theMesh != NULL && !meshConstructionFlag){
                theMesh->hit(0.5,0.5,v,globalForces.excitationType,globalForces.excitationShape);
            }
        }else{
            //theMesh->damp();
        }
    }
    if(msg.status == MIDI_NOTE_OFF){
        if(msg.pitch == p){
            //theMesh->damp();
        }
        // otherwise ignore it, it's not the currenttly playing note
    }
    
}

//--------------------------------------------------------------
void testApp::midiInputAdded(string name, bool isNetwork) {
	stringstream msg;
	msg << "ofxMidi: input added: " << name << " network: " << isNetwork;
    cout << msg.str();
	addMessage(msg.str());
	
	// create and open a new input port
	ofxMidiIn * newInput = new ofxMidiIn;
	newInput->openPort(name);
	newInput->addListener(this);
	inputs.push_back(newInput);
}

//--------------------------------------------------------------
void testApp::midiInputRemoved(string name, bool isNetwork) {
	stringstream msg;
	msg << "ofxMidi: input removed: " << name << " network: " << isNetwork << endl;
    cout << msg.str();
	addMessage(msg.str());
	
	// close and remove input port
	vector<ofxMidiIn*>::iterator iter;
	for(iter = inputs.begin(); iter != inputs.end(); ++iter) {
		ofxMidiIn * input = (*iter);
		if(input->getName() == name) {
			input->closePort();
			input->removeListener(this);
			delete input;
			inputs.erase(iter);
			break;
		}
	}
}

//--------------------------------------------------------------
void testApp::midiOutputAdded(string name, bool isNetwork) {
	stringstream msg;
	msg << "ofxMidi: output added: " << name << " network: " << isNetwork << endl;
    cout << msg.str();
	addMessage(msg.str());
	
	// create and open new output port
	ofxMidiOut * newOutput = new ofxMidiOut;
	newOutput->openPort(name);
	outputs.push_back(newOutput);
}

//--------------------------------------------------------------
void testApp::midiOutputRemoved(string name, bool isNetwork) {
	stringstream msg;
	msg << "ofxMidi: output removed: " << name << " network: " << isNetwork << endl;
    cout << msg.str();
	addMessage(msg.str());
	
	// close and remove output port
	vector<ofxMidiOut*>::iterator iter;
	for(iter = outputs.begin(); iter != outputs.end(); ++iter) {
		ofxMidiOut * output = (*iter);
		if(output->getName() == name) {
			output->closePort();
			delete output;
			outputs.erase(iter);
			break;
		}
	}
}
//--------------------------------------------------------------