changeset 4:7541aeaebcdc

presest store locally. bit crap still though.
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Tue, 04 Dec 2012 18:36:00 +0000
parents 43df75088d85
children 5ee5ef99e117
files 2dvector.h eventLogger.h eventLogger.mm frequencer.h frequencer.mm grid.mm presetManager.h presetManager.mm testApp.mm
diffstat 9 files changed, 1191 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/2dvector.h	Mon Dec 03 18:29:07 2012 +0000
+++ b/2dvector.h	Tue Dec 04 18:36:00 2012 +0000
@@ -40,6 +40,8 @@
 // output text formatting: (x,y) in super precise output 
 inline ostream& operator<<(ostream& ostr, const TwoVector& tvec){
     ostr.setf(ios_base::fixed,ios_base::floatfield);
+    ostr.precision(1);
+    
     ostr << "(" << tvec.x << "," << tvec.y << ")";
     return ostr;
 }
@@ -53,21 +55,23 @@
         cout << "BAD INPUT";
         return istr;
     }
+    
     istr.setf(ios_base::fixed,ios_base::floatfield);
+    istr.precision(1);
     
-    istr >> l_paren;
+    istr >> l_paren >> tvec.x >> comma >> tvec.y >> r_paren;
     if(l_paren != '('){
-        cout << "BAD INPUT";
+        cout << "BAD INPUT (";
         return istr;
     }
-    istr >> tvec.x;
+
     if(comma != ','){
-        cout << "BAD INPUTa";
+        cout << "BAD INPUT ,";
         return istr;
     }
-    istr >> tvec.y;
+
     if(r_paren != ')'){
-        cout << "BAD INPUT";
+        cout << "BAD INPUT )";
         return istr;
     }
     return istr;
--- a/eventLogger.h	Mon Dec 03 18:29:07 2012 +0000
+++ b/eventLogger.h	Tue Dec 04 18:36:00 2012 +0000
@@ -12,30 +12,41 @@
 #define __oscSenderExample__eventLogger__
 
 
+#include "ofMain.h"
+#include "ofxiPhone.h"
+#include "2dvector.h"
+#include "ofxiPhoneExtras.h"
+#include <sys/time.h>
+#include <iostream>
+#include <string>
+#include <map>
+#include "2dvector.h"
+enum leventType {SAVE_PRESET, SAVE_DESET, SCROLL, ZOOM, CHANGE_SLIDER, SWAP_VIEW};
 
-#include <iostream>
-#include "2dvector.h"
-enum eventType {PRESET, DESET, SCROLL, ZOOM, SLIDER};
+class lEvent{
 
-class Event{
     // try and make this as compact as possible.
-    int eventType; // -4 save deset, -3 save preset, -2 zoom, -1 scroll, 0-D slider index
+    leventType eventType;
     double val1; // x coord, scale if zoom
     double val2; // y coord, 0 if zoom
+    int sliderID;
+    
 };
 
+
+
 class EventLogger{
 public:
     // what we need...
     /*
      time, type, value
      */
-    vector<Event> events;
+    vector<lEvent> theEvents;
     
-    int userID; // get something from hardware??
+    string userID; // get something from hardware??
     
     EventLogger();
-    void logEvent(int evtType,TwoVector centre, double scale);
+    void logEvent(const leventType& evtType,const TwoVector& centre, const double& scale, const int& sliderID);
     void sendHttp();
 };
 
--- a/eventLogger.mm	Mon Dec 03 18:29:07 2012 +0000
+++ b/eventLogger.mm	Tue Dec 04 18:36:00 2012 +0000
@@ -5,11 +5,7 @@
 //  Created by Robert Tubb on 05/11/2012.
 //
 //
-#include "ofMain.h"
-#include "ofxiPhone.h"
-#include "2dvector.h"
-#include "ofxiPhoneExtras.h"
-#include <sys/time.h>
+
 
 #include "eventLogger.h"
 
@@ -17,16 +13,21 @@
 EventLogger eventLogger;
 
 EventLogger::EventLogger(){
-
-    // if first time opened request a user ID from the server. use time?
+    
+    // if first time opened request a user ID from the server... use time?
 
     double timemsd = [NSDate timeIntervalSinceReferenceDate];
     long long timems = (long long)(timemsd*1000);
     cout << "Time (ms) = " << timems << "\n";
+    
+    
+    CFUUIDRef theUUID = CFUUIDCreate(NULL);
+    CFStringRef tstring = CFUUIDCreateString(NULL, theUUID);
+    CFRelease(theUUID);
 
 }
 
-void EventLogger::logEvent(int evtType, TwoVector centre, double scale = 0.0){
+void EventLogger::logEvent(const leventType& evtType,const TwoVector& centre, const double& scale = 1.0, const int& sliderID = -1){
     //cout << "log: " << evtType << "\n";
     
     // scroll has 2 double coords
@@ -35,19 +36,29 @@
     // switch view has view type
     // slider change has int slider index and 1 int value
     
-    // store in local vector
-    if(evtType == -4){
-        // save deset
-    }else if(evtType == -3){
-        // save preset
-    }else if(evtType == -2){
-        // save preset
-    }else if(evtType == -1){
-        // save preset
-        cout << "move:\t" << centre << "\n";
-    }else{
-        // slider change
+    // get time for key index
+    
+    switch ( evtType ) {
+        case SAVE_PRESET:
+            // Code
+            break;
+        case SAVE_DESET:
+            // Code
+            break;
+        case SCROLL:
+            // Code
+            break;
+        case ZOOM:
+            // Code
+            break;
+        case CHANGE_SLIDER:
+            // Code
+            break;
+        default:
+            // Code
+            break;
     }
+
     
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frequencer.h	Tue Dec 04 18:36:00 2012 +0000
@@ -0,0 +1,42 @@
+//
+//  frequencer.h
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 27/11/2012.
+//
+// This is a C++ version of freqMaster.js max script
+
+#ifndef __oscSenderExample__frequencer__
+#define __oscSenderExample__frequencer__
+
+#include <iostream>
+#include "ofMain.h"
+#include "math.h"
+
+
+class Frequencer{
+    
+private:
+    vector<double> timePoints;
+    vector<double> freqMag;
+    vector<double> freqPhase;
+    int N;
+    
+    
+    void dft();
+    void idft();
+public:
+    Frequencer();
+    void clear();
+    void timeEdit(int n, double value);
+    void timeEdit(vector<double> allValues);
+    void freqMagEdit(int k, double mag);
+    vector<double> freqMagEdit(vector<int> indexes, vector<double> values);
+    void freqPhaseEdit(int k, double phase);
+    vector<double> freqPhaseEdit(vector<int> indexes, vector<double> values);
+
+    double getPoint(int idx);
+    //int getPoint(int idx); // rounded
+};
+
+#endif /* defined(__oscSenderExample__frequencer__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frequencer.mm	Tue Dec 04 18:36:00 2012 +0000
@@ -0,0 +1,167 @@
+//
+//  frequencer.cpp
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 27/11/2012.
+//
+//
+
+#include "frequencer.h"
+Frequencer frequencer;
+
+Frequencer::Frequencer(){
+    
+    N = 16;
+
+    for(int i = 0; i<N;i++){
+        timePoints.push_back(0.0);
+        freqMag.push_back(0.0);
+        freqPhase.push_back(0.0);
+    }
+    
+}
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
+
+void Frequencer::timeEdit(int n, double value){
+
+    // update internal
+    timePoints[n] = value;
+    
+    // calculate transform
+    dft();
+
+    //TODO  output freq domain - to PD
+
+}
+
+void Frequencer::timeEdit(vector<double> allValues){
+    
+    // update internal
+    vector<double>::iterator iter;
+    vector<double>::iterator iter2;
+    iter = allValues.begin();
+    iter2 = timePoints.begin();
+    for (iter = allValues.begin(); iter < allValues.end(); iter++,iter2++){
+        *iter = *iter2;
+    }
+    
+    
+    // calculate transform
+    dft();
+    
+    //TODO  output freq domain - to PD
+    
+}
+
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
+
+void Frequencer::freqMagEdit(int k, double mag){
+    // put into local store,
+   
+    freqMag[k] = mag;
+    
+    // making sure to conjugate
+    
+    freqMag[N-k] = freqMag[k];
+    
+    
+    // calculate transform
+    idft();
+    
+    
+    //TODO output time domain
+
+    
+}
+
+vector<double> Frequencer::freqMagEdit(vector<int> indexes, vector<double> values){
+    if(indexes.size() != values.size()){
+        cout << "freqMagEdit error: indexes dont match values\n";
+        return timePoints;
+    }
+    // put into local store,
+    for(int i=0;i<indexes.size();i++){
+        freqMag[indexes[i]] = values[i];
+        freqMag[N-indexes[i]] = freqMag[indexes[i]];
+    }
+   
+    // calculate transform
+    idft();
+
+    return timePoints;
+}
+
+
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
+
+void Frequencer::freqPhaseEdit(int k, double phase){
+    N = 16;
+    // put into local store
+    freqPhase[k] = phase;
+    
+    // making sure to conjugate
+    
+    freqPhase[N-k] = - freqPhase[k];
+    
+    // calculate transform
+    idft();
+    // TODO output time domain
+   
+}
+
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
+
+void Frequencer::dft(){
+    
+    // we have 16 time points. work out freqs and phases
+    int n = 0;
+    int k = 0;
+    double xre = 0.;
+    double xim = 0.;
+    
+    for(k=0; k < N; k++){
+        // work out xn
+        xre = 0.;
+        xim = 0.;
+        for(n=0;n < N;n++){
+            xre = xre + timePoints[n]*cos( (2.*PI/(float)N)*n*k);
+            xim = xim + timePoints[n]*sin( (2.*PI/(float)N)*n*k);
+            
+        }
+        freqMag[k] = sqrt(pow(xre,2) + pow(xim,2.)); // MAGNITUDE
+        freqPhase[k] = -atan2(xim,xre);
+    }
+    
+}
+
+
+
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
+
+void Frequencer::idft(){
+    
+    // we have some freqs and phases. work out real time points (conj)
+    int n = 0;
+    int k = 0;
+    double xre = 0.;
+    double xim = 0.;
+    
+    for(n=0; n < N; n++){
+        // work out xn
+        xre = 0.;
+        xim = 0.;
+        for(k=0;k < N;k++){
+            xre = xre + freqMag[k]*cos( (2.*PI/(float)N)*n*k + freqPhase[k]);
+            
+        }
+        timePoints[n] = xre/(float)N; // divided by N ???
+    }
+    
+}
+/////////////////////////////////////////////////////
+/////////////////////////////////////////////////////
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/grid.mm	Tue Dec 04 18:36:00 2012 +0000
@@ -0,0 +1,826 @@
+//
+//  grid.cpp
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 03/10/2012.
+//
+//
+
+#include "grid.h"
+
+
+#include <sstream>
+
+extern PresetManager presetManager;
+extern EventLogger eventLogger;
+//--------------------------------------------------------------
+Grid::Grid(): maxValue(pow(32.0,7.0)-1), minValue(60),     paramsPerDim(5), paramBitDepth(7){
+
+}
+//--------------------------------------------------------------
+//--------------------------------------------------------------
+Grid::~Grid(){
+
+}
+void Grid::init(){
+    //maxValue = pow(32.0,7.0)-1;
+    //minValue = 60; // number of 1-size divisions at smallest scale
+    maxZoom = false;
+    minZoom = false;
+
+    codeLength = pow(2.0,paramsPerDim);
+    
+    pixSize.setCoord(ofGetWidth(), ofGetHeight());
+ 
+    //set scale and position to mid way
+    scale = pow(32.0,6.0);
+    
+
+    size.setCoord(pixSize.x*scale, pixSize.y*scale);
+    centre.setCoord(maxValue/2 , maxValue/2);
+    topLeft.setCoord(centre.x - size.x/2, centre.y - size.y/2);
+    
+    
+    makeCode();
+
+    // set a starting param value, find coord that does it.
+    vector<int> params(paramsPerDim*2);
+    for(int i = 0;i<2*paramsPerDim;i++){
+        midiCC[i] = 12;
+        params[i] = 12;
+    }
+    TwoVector coord = calculateCoordFromParams(params);
+    setCoord(coord);
+    
+    viewWasChanged();
+    
+    
+    
+}
+
+template <typename T> int sgn(T val) {
+    return (T(0) < val) - (val < T(0));
+}
+
+void Grid::makeCode(){
+ 
+    ////////////////////////////////~~~,,,,,,,,.........
+    ////////// gray code generation
+    //////
+    ///
+    // TODO 5bit specific
+    // transition sequence.... what a palaver! only need to do once though.
+    int trans[] = {0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3,0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3};
+
+    
+    int code[codeLength][paramsPerDim]; // start with normal array
+    
+   
+    
+    for(int j=0; j<paramsPerDim; j++){
+        code[0][j] = 0;
+    }
+    
+    for(int i=0; i < codeLength-1; i++){  // TODO went off end??
+        transSeq.push_back(trans[i]); // member vector
+        for(int j=0; j<paramsPerDim; j++){
+            
+            if (j == abs(trans[i])){
+                code[i+1][j] = !code[i][j];
+            }else{
+                code[i+1][j] = code[i][j]; 
+            }
+        }
+
+    }
+    
+    for(int i=0; i < codeLength; i++){ // fill vector
+        
+        vcode.push_back(vector<bool>());
+        
+        for(int j=0; j<paramsPerDim; j++){
+            vcode[i].push_back(code[i][j]);
+        }
+    }
+    
+    // now try with iterators to print...
+    vector< vector<bool> >::iterator cit;
+    //vector<bool>::iterator bit;
+    vector<bool>::iterator bit;
+    int i = 0;
+    for(cit=vcode.begin(); cit!=vcode.end() ; cit++){ // fill vector
+        i++;
+        cout << i << " = ";
+        bit = (*cit).begin();
+        for(bit=(*cit).begin(); bit!=(*cit).end() ; bit++){
+            
+            cout  << *bit;
+        }
+        cout << "\n";
+
+    }
+    /*
+    // codeToInt unit test
+    vector<bool> aCode = vcode[12];
+    int result = grayToInt(aCode);
+    cout << "GRAY TO INT : " << result << "\n";
+
+    cout << "-------------------------------\n";
+    
+    // base32toFloat unit test
+
+    vector<int> test32 = coordTobase32(869437.0);
+    double cresult = base32toCoord(test32);
+    cout << "base32toCoord : " << cresult << "\n";
+     
+     cout << "-------------------------------\n";
+    
+    
+    
+    // midiToGray unit test
+
+    vector<vector<bool> > incodes(paramBitDepth, vector<bool>(paramsPerDim));
+    for(int i=0;i<7;i++){
+        incodes[i] = vcode[i+5];
+    }
+
+    vector<int> midiTest;
+    midiTest = grayToMidi(incodes);
+    vector<vector<bool> > outcodes = midiToGray(midiTest);
+    
+    vector< vector<bool> >::iterator cit1;
+    //vector<bool>::iterator bit;
+    vector<bool>::iterator bit1;
+    cout << "midiToGray Unit test\n";
+    for(int i=0;i<paramBitDepth;i++){ // fill vector
+
+        for(int j=0;j<paramsPerDim;j++){
+            
+            cout  << (incodes[i][j] == outcodes[i][j]) << ",";
+        }
+        cout << "\n";
+        
+    }
+     cout << "-------------------------------\n";
+
+    
+    // whole process unit test(?)
+    
+    TwoVector inCoord(888999777,777666555);
+    vector<int> checkParam;
+    checkParam = calculateParamsFromCoord(inCoord);
+    for(int i=0; i<2*paramsPerDim;i++){
+        cout << checkParam[i] << "_";
+    }
+    TwoVector outCoord = calculateCoordFromParams(checkParam);
+    cout << "Unit TEst coord = " << outCoord.x << "," << outCoord.y << "\n";
+*/
+    
+}
+//--------------------------------------------------------------
+void Grid::draw(){  // draw lines
+    // TODO too friggin long
+    
+    //scale++;
+    // nice loopy thing
+    int power = 0;
+   
+    // these get big!
+    double  divsr;
+    double yl,xl;
+    double gridSize = 0;
+
+    double firstLineXPos, lastLineXPos,firstLineYPos, lastLineYPos, remleft, xoffset, yoffset = 0.0;
+    double xstart, xfinish, ystart,yfinish;
+    // these don't
+    int xpos, ypos = 0;
+    
+    float alpha;
+    bool done = false;
+    float markpow = 32.0;  // power that denotes next grid markings
+    int lineWidth = 0;
+    int colCycle = 0;
+
+ 
+    // loop thru powers of (base?) to determine which should be shown as grids
+    while (!done){
+        gridSize = pow(markpow,power);
+ 
+        colCycle = power % 7;
+
+        divsr = size.x / gridSize;
+
+        // if (divisor i.e. number of lines is less than 1000
+        if( divsr >= 1 && divsr < 1000){
+
+            // calculate transparency
+            float visCont = log10(divsr); // 0 if only 1 line, 3 if 1000 lines
+            alpha = 90*(3 - visCont);
+            ofSetLineWidth(lineWidth);
+            
+            // cycle colors for different scales
+            if(colCycle == 0){
+                ofSetColor(255,255,255,alpha);
+            }else if(colCycle == 1){
+                ofSetColor(255,0,0,alpha);
+            }else if(colCycle == 2){
+                ofSetColor(0,0,255,alpha);
+            }else if(colCycle == 3){
+                ofSetColor(0,255,0,alpha);
+            }else if(colCycle == 4){
+                ofSetColor(255,0,255,alpha);
+            }else if(colCycle == 5){
+                ofSetColor(0,255,255,alpha);
+            }else if(colCycle == 6){
+                ofSetColor(255,255,0,alpha);
+            }else if(colCycle == 7){
+                ofSetColor(255,255,255,alpha);
+            }else{
+                cout << "err colour messed up\n";
+            }
+            
+            
+            // draw level numbers associated with each color. This would not be true if markpow wasnt 2^d
+            ////////-------/////////
+            /*
+            temp << "THIS LEVEL = " << (int)pow(2.0,power) << "   ";
+            string s = temp.str();
+            ofDrawBitmapString( s, 10, line );
+            line+=30;
+            temp.str("");
+            *////////-------/////////
+            
+            // draw presets at this level
+            // fill in smallest squares if they contain a preset
+            // how to do this efficiently?
+            
+            
+            if(topLeft.x < 0.0){
+                firstLineXPos = 0.0;
+                xoffset = firstLineXPos - topLeft.x;
+                xstart = xoffset/scale;
+            }else{
+                firstLineXPos = topLeft.x;
+                // kinda float version of % operator
+                remleft = ceil(firstLineXPos/gridSize);
+                xoffset = (remleft * gridSize) - topLeft.x;
+                xstart = 0;
+            }
+            if(topLeft.x + size.x > maxValue){
+                lastLineXPos = maxValue+1 - topLeft.x;
+                
+                
+            }else{
+                lastLineXPos = size.x;
+                
+            }
+            xfinish = lastLineXPos/scale;
+            
+            //////////------------------------
+            // same for y
+            
+            if(topLeft.y < 0.0){
+                firstLineYPos = 0.0;
+                yoffset = firstLineYPos - topLeft.y;
+                ystart = yoffset/scale;
+            }else{
+                firstLineYPos = topLeft.y;
+                // kinda float version of % operator
+                remleft = ceil(firstLineYPos/gridSize);
+                yoffset = (remleft * gridSize) - topLeft.y;
+                ystart = 0;
+            }
+            if(topLeft.y + size.y > maxValue){
+                lastLineYPos = maxValue+1 - topLeft.y;
+               
+            }else{
+                lastLineYPos = size.y;
+                
+            }
+            yfinish = lastLineYPos/scale;
+            // -------------------------------------------
+                // now draw
+            for(xl = xoffset; xl <= (lastLineXPos); xl+= gridSize){
+
+                xpos = xl/scale;
+                ofLine(xpos, ystart, xpos, yfinish);
+            
+            }
+
+            for(yl = yoffset; yl <= (lastLineYPos); yl+= gridSize){
+                
+                ypos = yl/scale;
+                ofLine(xstart, ypos, xfinish, ypos);
+            }
+            
+            
+        }else if (divsr < 1){
+            // ignore...
+            done = true;
+        }
+        
+        power++;
+    }
+    //cout << "draw done" << "\n";
+    //displayInfo();
+
+    drawPresets();
+    ////////-------/////////
+    
+    ////////-------/////////
+    
+    // draw centre cross hairs
+    ofSetColor(255, 0, 0);
+    ofNoFill();
+    ofLine(pixSize.x/2-20, pixSize.y/2, pixSize.x/2+20, pixSize.y/2);
+	ofLine(pixSize.x/2, pixSize.y/2-20, pixSize.x/2, pixSize.y/2+20);
+    ofEllipse(pixSize.x/2, pixSize.y/2, 20, 20);
+    ofFill();
+    ////////-------////////
+    /*
+    ostringstream temp;
+    temp << "Centre x = " << centre.x << "\n      y = " << centre.y << "   ";
+    string s = temp.str();
+    ofDrawBitmapString( s, pixSize.x/2+10, pixSize.y/2+10 );
+    */
+}
+TwoVector Grid::coordToPixel(TwoVector coord){
+    TwoVector pix;
+    pix.x = (coord.x - topLeft.x)/scale;
+    pix.y = (coord.y - topLeft.y)/scale;
+    return pix;
+    
+}
+
+//-----------------------------------------------------------------------
+void Grid::drawPresets(){
+    vector<TwoVector> points;
+    TwoVector pos;
+    points = presetManager.getPresetsInRange(topLeft, topLeft + size);
+    vector<TwoVector>::iterator piter;
+    for(piter = points.begin(); piter < points.end(); piter++){
+        ofSetColor(255, 255, 255, 200);
+        pos = coordToPixel(*piter);
+        ofCircle(pos.x, pos.y, 2);
+        
+    }
+}
+
+//-----------------------------------------------------------------------
+void Grid::displayInfo(){
+    
+    // display some "useful information"
+    
+    ofSetColor(255,255,255,255);
+    
+    ostringstream temp;
+    int line = 10; // text output pos
+    
+    
+    ////////-------/////////
+    temp << "scale = " << scale << "   ";
+    string s = temp.str();
+	ofDrawBitmapString( s, 10, line );
+    line+=30;
+    temp.str("");
+    ////////-------/////////
+    temp << "Top Left = " << topLeft.x << "," << topLeft.y << "   ";
+    s = temp.str();
+    ofDrawBitmapString( s, 10, line );
+    line+=60;
+    temp.str("");
+    
+    ////////-------/////////
+    temp << "View Size = " << size.x << "," << size.y << "   ";
+    s = temp.str();
+    ofDrawBitmapString( s, 10, line );
+    line+=60;
+    temp.str("");
+    
+    ////////-------/////////
+    
+    for(int i=0;i<10;i++){ // TODO 5bit specific
+        temp << midiCC[i] << " ";
+        s = temp.str();
+        ofDrawBitmapString( s, 10, line );
+        line+=20;
+        temp.str("");
+    }
+}
+ //--------------------------------------------------------------
+void Grid::update(){  // ?
+    // "update" bit of a crap name - all we do here is calculate the dimension params from the x,y position
+
+
+}
+//--------------------------------------------------------------
+void Grid::move(TwoVector moveP){
+    // numspacing, pixelspacing stay the same
+    
+    // convert pixels to surf units
+    TwoVector moveS;
+    moveS = moveP * scale;
+    
+    topLeft = topLeft - moveS;  // - because moving to the right means taking away from offset
+    centre = centre - moveS;
+    
+    viewWasChanged();
+    eventLogger.logEvent(-1, centre, scale);
+    
+}
+//--------------------------------------------------------------
+void Grid::zoom(float factor){
+    if(maxZoom && factor > 1.0){
+        return;
+        
+    }
+    if(factor < 1.0){
+        maxZoom = false;
+    }
+    if(minZoom && factor < 1.0){
+        return;
+        
+    }
+    if(factor > 1.0){
+        minZoom = false;
+    }
+    scale = scale*factor; // simple eh?
+
+    // update view size using centre
+    // and scale...
+    size.x = size.x*factor; // zooming in, size gets SMALLER (view less)
+    size.y = size.y*factor;
+
+    
+    
+    viewWasChanged();
+    eventLogger.logEvent(-2, centre, scale);
+
+} 
+void setMaxZoom(){ // got to smallest (white)
+    
+}
+//--------------------------------------------------------------
+void setMinZoom(){ // go to entire space (orange)
+    
+}
+//--------------------------------------------------------------
+void Grid::viewWasChanged(){
+    checkLimits();
+    // and calculate new params?
+    
+    vector<int> params = calculateParamsFromCoord(centre);
+    for(int i = 0;i<2*paramsPerDim;i++){
+        midiCC[i] = params[i];
+    }
+    // update sliders if nec.
+
+}
+
+//--------------------------------------------------------------
+void Grid::checkLimits(){
+    // check for maximum zoom level
+    // TODO: DODGY
+
+    if(size.x > maxValue*2.0){
+        cout << "maxZoom\n";
+        maxZoom = true;
+        size.x = maxValue*2.0;
+        // need to also set y size back to
+    }
+    if(size.y > maxValue*2.0){
+        cout << "maxZoom\n";
+        maxZoom = true;
+        size.y = maxValue*2.0;
+    }
+    
+    if(size.x < minValue){
+        cout << "min Zoom\n";
+        minZoom = true;
+        size.x = minValue;
+        // need to also set y size back to
+    }
+    if(size.y < minValue){
+        minZoom = true;
+        cout << "min Zoom\n";
+        size.y = minValue;
+    }
+    
+    scale = size.x/pixSize.x;
+    size.y = scale * pixSize.y;
+    
+    topLeft.x = centre.x - size.x/2;
+    topLeft.y = centre.y - size.y/2;
+    // check for negatives
+    
+    // allow centre to be at limits
+    if((topLeft.x + size.x*0.5) < 0.0){
+        cout << "left Wall\n";
+        topLeft.x = 0.0 - size.x*0.5;
+        centre.x = 0.0;
+    }
+
+    if(topLeft.y + size.y*0.5 < 0.0) {
+        cout << "top Wall\n";
+        topLeft.y = 0.0 - size.y*0.5;
+        centre.y = 0.0;
+    }
+    
+   // does topleft refer to lines or view?
+    
+        // check max 
+    if(topLeft.x + size.x/2 > maxValue){
+        cout << "right Wall\n";
+        topLeft.x = maxValue - size.x/2;
+        centre.x = maxValue;
+    }
+    if(topLeft.y + size.y/2 > maxValue) {
+        cout << "bottom Wall\n";
+        topLeft.y = maxValue - size.y/2;
+        centre.y = maxValue;
+    }
+
+}
+//--------------------------------------------------------------
+void Grid::checkConsistencies(){
+    // debug function to check all the parameters are consistent maybe
+
+}
+//--------------------------------------------------------------
+void Grid::setCoord(TwoVector coord){
+    
+    centre = coord;
+    viewWasChanged();
+}
+//--------------------------------------------------------------
+TwoVector Grid::getCoord(){
+    
+    return centre;
+}
+//--------------------------------------------------------------
+vector<int> Grid::getParams(){
+    // return a vector with midiCCs in
+    // should we store params somewhere and use this as a low computation get ?
+    vector<int> params(2*paramsPerDim,0);
+    //
+    for(int i = 0;i<2*paramsPerDim;i++){
+        params[i] = midiCC[i];
+    }
+    return params;
+}
+//--------------------------------------------------------------
+void Grid::setParams(vector<int> params){
+    // input midiCCs, and go to the appropriate coordinate
+
+    for(int i = 0;i<2*paramsPerDim;i++){
+        midiCC[i] = 64;
+    }
+    TwoVector coord = calculateCoordFromParams(params);
+    setCoord(coord);
+    
+    viewWasChanged();
+
+}
+//--------------------------------------------------------------
+TwoVector Grid::calculateCoordFromParams(vector<int> params) const{
+
+    vector<int> ccValueX(paramsPerDim);
+    vector<int> ccValueY(paramsPerDim);
+    for(int i=0;i<paramsPerDim;i++){
+        ccValueX[i] = params[i];
+        ccValueY[i] = params[i+paramsPerDim];
+    }
+    vector<vector <bool> > codesX = midiToGray(ccValueX);
+    vector<vector <bool> > codesY = midiToGray(ccValueY);
+
+    vector<int> base32X = codesToBase32(codesX);
+    vector<int> base32Y = codesToBase32(codesY);
+    
+    TwoVector result;
+    result.x = base32toCoord(base32X);
+    result.y = base32toCoord(base32Y);
+    return result;
+}
+
+//--------------------------------------------------------------
+vector<int> Grid::calculateParamsFromCoord(TwoVector coord) const{
+    // some arrays in reverse order of power from normal numbers!   1,2,4,
+    
+    // centre to base 32
+    if (coord.x > maxValue || coord.y > maxValue){
+        cout << "calculateParams Error: centre double value is too large" << "\n";
+        vector<int> empty;
+        return empty;
+    }
+
+    //--------------------------
+    // X
+    vector<int> base32x = coordTobase32(coord.x); // 7 numbers from 0 to 31
+    vector<vector <bool> > grayCodesX;
+    
+    int size = base32x.size();
+    for(int i=0;i<size;i++){
+        grayCodesX.push_back(intToGray(base32x[i]));
+    }
+    
+    vector<int> result;
+    result = grayToMidi(grayCodesX);
+    //--------------------------
+    // AND FOR Y
+    vector<int> base32y = coordTobase32(coord.y);
+    vector<vector <bool> > grayCodesY;
+    
+    size = base32y.size();
+    for(int i=0;i<size;i++){
+        grayCodesY.push_back(intToGray(base32y[i]));
+    }
+
+    vector<int> resultY;
+    resultY = grayToMidi(grayCodesY);
+    
+    // concatenate
+    result.insert( result.end(), resultY.begin(), resultY.end() );
+    return result;
+}
+//-------------------------------------------------------------------
+
+// for 1 dimension!!! i.e. call this twice
+vector<int> Grid::grayToMidi(vector<vector <bool> > grayCodes) const{
+
+    // gray to midi CC values
+    // loop thru the scales to build up a CC number per dimension
+    int midiCCresult[paramsPerDim]; // TODO dims specific
+    for(int i=0;i<paramsPerDim;i++){
+        midiCCresult[i] = 0;
+    }
+    
+    int bin = 1;
+    bin = bin << grayCodes.size()-1;
+    
+    int midP = 0;
+    
+    vector<vector <bool> >::iterator piter = grayCodes.begin();
+    for(;piter < grayCodes.end();piter++){ // each lesser power of 2
+        midP = 0; // reset
+        vector<bool>::iterator diter = (*piter).begin();
+        for(; diter <= (*piter).end();diter++){ // each one is different dimension
+            int ig = int(*diter); // convert binary to int
+            //cout << "ig: " << ig;
+            midiCCresult[midP] += ig*bin; // mult by power of two
+            midP++;
+        }
+        bin = bin >> 1; // next power of 2 down
+        
+    }
+    
+    // put in vector
+    vector<int> result;
+    for(int i=0;i<paramsPerDim;i++){
+        result.push_back(midiCCresult[i]);
+    }
+    
+    return result;
+    
+    
+}
+
+
+//--------------------------------------------------------------
+
+vector<bool> Grid::intToGray(int num, int dimToTravel) const{
+
+    // dimToTravel - this is the dimension that we want the walk to traverse, i.e. the last non zero digit of the code
+    // so swap it for 3 to produce correct orientation
+
+    // just use look up table... until it gets huuuge.
+    vector<bool> grayCode = vcode[num];
+    grayCode[3] = vcode[num][dimToTravel];
+    grayCode[dimToTravel] = vcode[num][3];
+    return grayCode;
+}
+//--------------------------------------------------------------
+vector<int> Grid::walkDiff(vector<bool> left, vector<bool> right){
+    // horrible
+    vector<int> result(2,0);
+
+    int size = left.size();
+    for(int i = 0; i < size; i++){
+        if(left[i] && !right[i]){  // 1 - 0
+            // dim
+            result[0] = i;
+            result[1] = 1;
+        }else if(!left[i] && right[i]){ // 0 - 1
+            result[0] = i;
+            result[1] = -1;
+        }else{ // equal do nothing
+            
+            
+        }
+    }
+    
+    return result;
+}
+
+//--------------------------------------------------------------
+/*
+breaks down float into a base 32 number (2^D)
+each of these is converted to gray code
+this is then converted to 10 parameters, where each 32-digit becomes separate power of 2
+ so "zoom" grid 32-patches are converted to 2-scales. 1,2,4,8,16,32,64,(128?) biggest number is 32^7
+*/
+vector<int> Grid::coordTobase32(double value) const{
+    //double base = 32.0;
+    if(value < 0.0){
+        cout << "coordTobase32 error: input value is negative\n";
+        value = 0.0;
+    }else if(value > maxValue){
+        cout << "coordTobase32 error: input value too big!\n";
+    }
+    double rem, divdr = 0.0;
+    int digit32;
+
+    // what power of 32 to start at?
+    int maxpow = 7; // midi cc specific
+    vector<int> result; 
+
+    rem = value;
+    for(;maxpow >=0;maxpow--){
+        // repeatedly get digit and remainder. This is exactly what we're doing in draw !?... could put all this in one place?
+        divdr = pow((double)codeLength,(double)maxpow);
+        digit32 = floor(rem/divdr);
+        rem = rem - digit32*divdr; 
+        result.push_back(digit32);  // array, biggest index is smallest power
+    }
+    // at this point rem should be fractional... use for interp?
+
+    return result;
+}
+//--------------------------------------------------------------
+
+// WHY HERE XCODE?
+vector<int> Grid::codesToBase32(vector<vector<bool> > inCodes) const{
+    vector<int> result;
+    for(int i=0;i<paramBitDepth;i++){
+        result.push_back(grayToInt(inCodes[i]));
+    }
+    return result;
+}
+//--------------------------------------------------------------
+
+int Grid::grayToInt(vector<bool> incode) const{
+    // look for match in table
+    
+    int s = vcode.size();
+    
+    for(int i=0; i<s;i++){ // fill vector
+        if(vcode[i] == incode){
+            return i;
+        }
+        
+    }
+    cout << "grayToInt error: no matching code found!";
+    return -1;
+}
+//--------------------------------------------------------------
+double Grid::base32toCoord(vector<int> base32Digs) const{
+    // build up the big float from a base 32 number
+    double result = 0.0;
+   
+    // what power of 32 to start at?
+    int mpow = base32Digs.size() - 1; // should be 7...
+    
+    for(int p=0;p<=mpow;p++){ // biggest index is smallest power
+        result += ((double)base32Digs[p]) * pow(32.0, (double)mpow-p);
+  
+    }
+    return result;
+    
+}
+//--------------------------------------------------------------
+// for 1 dimension - takes in 5 cc params and outputs  7 codes 
+vector<vector <bool> > Grid::midiToGray(vector<int> ccValue) const{
+    int pow2 = 1 << (paramBitDepth-1);
+
+    vector<int> aCode(paramsPerDim);
+    vector<vector<int> > theXCodes(paramBitDepth,aCode);
+    
+    // build up binary gray code representations from the bits of the midi ccs
+
+    vector<vector<bool> > theCodes(paramBitDepth, vector<bool>(paramsPerDim));
+
+    // x
+    for(int p=0;p<paramBitDepth;p++){
+
+        for(int i=0;i<paramsPerDim;i++){
+            
+            bool bit = (pow2 == (ccValue[i] & pow2));
+            theCodes[p][i] = bit;
+        }
+        pow2 = pow2 >> 1;
+        
+    }
+    return theCodes;
+}
+//--------------------------------------------------------------
+//--------------------------------------------------------------
+//--------------------------------------------------------------
\ No newline at end of file
--- a/presetManager.h	Mon Dec 03 18:29:07 2012 +0000
+++ b/presetManager.h	Tue Dec 04 18:36:00 2012 +0000
@@ -23,18 +23,34 @@
 
     int presetID;
     string name;
+    long long savetime;
+    double timemsd = [NSDate timeIntervalSinceReferenceDate];
+    
     TwoVector coordinates;
     
     Preset(TwoVector acoord, string aname,int aID){
         coordinates = acoord;
         name = aname;
         presetID = aID;
+        
+        timemsd = [NSDate timeIntervalSinceReferenceDate];
+        savetime = (long long)(timemsd*1000);
 
     };
     Preset(int aID){
         coordinates.setCoord(0.0,0.0);
         name = "Blank";
         presetID = aID;
+        timemsd = [NSDate timeIntervalSinceReferenceDate];
+        savetime = (long long)(timemsd*1000);
+        
+    };
+
+    Preset(TwoVector acoord, string aname,int aID, long long stime){
+        coordinates = acoord;
+        name = aname;
+        presetID = aID;
+        savetime = stime;
         
     };
 
@@ -42,20 +58,6 @@
 
 
 //---------------------------------------------------------------------------
-inline ostream& operator<<(ostream & os, const Preset& p)
-{
-    os << "Name:" << p.name << "|";
-    os << "Coord:" << p.coordinates << "\n";
-    
-    return(os);
-}
-//---------------------------------------------------------------------------
-inline istream& operator>>(istream & is, Preset& p)
-{
-    //um
-    return(is);
-}
-//---------------------------------------------------------------------------
 class PresetManager{
 public:
     int nextID;
@@ -66,14 +68,53 @@
     vector<Preset *> thePresets; // we want vector ? or list? pointers using new?
     
     int addPreset(TwoVector coord, string name); // returns id or negative error number
+    int loadPreset(const TwoVector coord, const string name, long long stime);
+    
     TwoVector recallPreset(int presetID); // by name ? id?
     TwoVector recallPreset(string name); // by name ? id?
     vector<TwoVector > getPresetsInRange(TwoVector min, TwoVector max);
+    void printAll();
     
     void startupLoadAll();  // get stuff from XML
     void exitAndSaveAll();  // save to XML, delete presets array (?)
+    void deleteAll();
     
     PresetManager();
 };
 
+
+//---------------------------------------------------------------------------
+inline ostream& operator<<(ostream & os, const Preset& p){
+    os.setf(ios_base::fixed,ios_base::floatfield);
+    os.precision(1);
+    
+    os << p.savetime << ',' << p.coordinates.x << ',' << p.coordinates.y << '\n';
+    
+    return os;
+}
+    
+    //---------------------------------------------------------------------------
+    inline istream& operator>>(istream & is, PresetManager& p)
+    {
+        //um
+        string pname = "BLANK";
+        char delim;
+        double px, py;
+        long long stime;
+        
+        
+        is.setf(ios_base::fixed,ios_base::floatfield);
+        is.precision(1);
+        
+        is >> stime >> delim >> px >> delim >> py;
+        if(!is){
+            cout << "problem reading preset file";
+            return(is);
+        }
+        TwoVector pcoord(px,py);
+        int n = p.loadPreset(pcoord, pname, stime);
+        cout << "read preset : " << n << '\n';
+        return(is);
+    }
+    
 #endif /* defined(__oscSenderExample__presetManager__) */
--- a/presetManager.mm	Mon Dec 03 18:29:07 2012 +0000
+++ b/presetManager.mm	Tue Dec 04 18:36:00 2012 +0000
@@ -16,11 +16,22 @@
 
 PresetManager::PresetManager(){
     timesOpened = 0;
+    nextID = 0;
     startupLoadAll();
-    
-    
-    nextID = 0;
-    
+  
+}
+//---------------------------------------------------------------------------
+void PresetManager::deleteAll(){
+    thePresets.clear();
+}
+//---------------------------------------------------------------------------
+void PresetManager::printAll(){
+    cout << "ALL PRESETS: \n";
+    vector<Preset *>::iterator presetIter;
+    for(presetIter = thePresets.begin(); presetIter < thePresets.end(); presetIter++){
+        cout << **presetIter << "\n";
+        
+    }
 }
 //---------------------------------------------------------------------------
 
@@ -51,6 +62,15 @@
     return nextID++;
 }
 //---------------------------------------------------------------------------
+
+int PresetManager::loadPreset(const TwoVector coord, const string name, long long stime){
+    
+
+    thePresets.push_back(new Preset(coord, name,nextID, stime));
+     // if ok
+    return nextID++;
+}
+//---------------------------------------------------------------------------
 vector<TwoVector > PresetManager::getPresetsInRange(const TwoVector min, const TwoVector max){
     //return all the coordinates. oh and names (displayed at certain scales?).
     
@@ -74,16 +94,20 @@
     // load file
   
     string fname = ofxiPhoneGetDocumentsDirectory() + "presets.dat";
-    char *fileName = (char*)fname.c_str();
-    ifstream from(fileName);
-    string line;
+    ifstream presetFile(fname.c_str());
 
     // simply prints file
-    while(from >> line){
-        cout << line << "\n";
-      
+    int i= 0;
+    if(!presetFile){
+        cout<<"no preset file";
+        return;
     }
-
+    while(presetFile >> *this){
+        cout << "loaded" << i++ << " presets\n";
+        // parse line
+        
+    }
+    presetFile.close();
 
 
     timesOpened++;
@@ -91,7 +115,7 @@
 //---------------------------------------------------------------------------
 void PresetManager::exitAndSaveAll(){
     ofFile presetFile(ofxiPhoneGetDocumentsDirectory() +"presets.dat",ofFile::WriteOnly);
-
+    
     cout << "Exit and save presets\n";
     vector<Preset *>::iterator presetIter;
 
@@ -99,8 +123,6 @@
         //vector<int> params;
         //params = theGridView.calculateParamsFromCoord((*presetIter)->coordinates);
         presetFile << **presetIter << "\n";
-        cout << **presetIter << "\n";
-
     }
     presetFile.close();
 
--- a/testApp.mm	Mon Dec 03 18:29:07 2012 +0000
+++ b/testApp.mm	Tue Dec 04 18:36:00 2012 +0000
@@ -34,7 +34,7 @@
     stringstream sstr;
     sstr << str;
     sstr >> ttest;
-    cout << "ttest: " << ttest.x << "\n";
+    cout << "ttest: " << ttest << "\n";
     
     
     prevTouch0.setCoord(1,2);
@@ -354,10 +354,13 @@
 
 //--------------------------------------------------------------
 void testApp::exit(){
+    
+    presetManager.exitAndSaveAll();
     core.exit();
-    presetManager.exitAndSaveAll();
+    
     delete standardGUI;
     delete zoomGUI;
+    cout << "exit done \n";
 }
 
 //--------------------------------------------------------------