changeset 0:a223551fdc1f

First commit - copy from tweakathlon.
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Fri, 10 Oct 2014 11:46:42 +0100
parents
children 7e0a19a538d4
files 2dvector.h 2dvector.mm AppCore.h AppCore.mm HelpViewController.h HelpViewController.mm HelpViewController.xib IntroViewController.h IntroViewController.mm IntroViewController.xib MessageOrganiser.h PDSynthWrapper.h Question.h Question.mm QuestionnaireViewController.h QuestionnaireViewController.mm QuestionnaireViewController.xib ServerComms.h ServerComms.mm SynthParam.h TestController.h TestController.mm TimedCallController.h TimedCallController.mm UI code/.DS_Store UI code/3Dbox.h UI code/3Dbox.mm UI code/3DboxGL.h UI code/3DboxGL.mm UI code/Buttron.h UI code/Buttron.mm UI code/ButtronSlider.h UI code/ButtronSlider.mm UI code/ButtronXY.h UI code/ButtronXY.mm UI code/CountdownText.h UI code/CountdownText.mm UI code/TextPanel.h UI code/TextPanel.mm UI code/UIElement.h UI code/UIElement.mm UI code/UIElementContainer.h UI code/UIElementContainer.mm UI code/UIGrid.h UI code/UIGrid.mm UI code/UIProperties.h UI code/buttonPanel.h UI code/buttonPanel.mm UI code/sliderPanel.h UI code/sliderPanel.mm UI code/targetSymbol.h UI code/targetSymbol.mm UI code/textLabel.h UI code/textLabel.mm UsernameAlertViewController.h UsernameAlertViewController.mm algorithms.mm eventLogger.h eventLogger.mm globalVariables.cpp globalVariables.h json/autolink.h json/config.h json/features.h json/json-forwards.h json/json.h json/reader.h json/value.h json/writer.h jsoncpp.mm main.mm pd patch/targetSynth7.pd targetSynth6.pd testApp.h testApp.mm timeController.h timeController.mm xyView.cpp xyView.h
diffstat 79 files changed, 21574 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2dvector.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,74 @@
+/*
+ *  2dvector.h
+ *  simplespring
+ *
+ *  Created by Robert Tubb on 01/06/2011.
+ *  Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+#ifndef _2DVECTORH
+#define _2DVECTORH
+#include <iostream>
+
+class TwoVector{
+public:
+	double x, y;
+	TwoVector();
+	TwoVector(double ax, double ay);
+
+// public methods	
+	double norm();
+	void setCoord(double ax, double ay);
+	TwoVector minus(TwoVector otherPoint);
+    TwoVector operator-(TwoVector otherPoint);
+    TwoVector operator+(TwoVector otherPoint);
+    
+    TwoVector operator*(TwoVector otherPoint);
+    TwoVector operator*(const double& scalar); // scalar is right operand
+
+    //TwoVector operator=(TwoVector otherPoint);
+    
+    double distanceTo(TwoVector otherPoint);
+
+};
+using namespace std;
+// 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;
+}
+inline istream& operator>>(istream& istr, TwoVector& tvec){
+        // um
+
+    char l_paren , comma, r_paren;
+    
+    
+    if(istr.bad()){
+        cout << "BAD INPUT";
+        return istr;
+    }
+    
+    istr.setf(ios_base::fixed,ios_base::floatfield);
+    istr.precision(1);
+    
+    istr >> l_paren >> tvec.x >> comma >> tvec.y >> r_paren;
+    if(l_paren != '('){
+        cout << "BAD INPUT (";
+        return istr;
+    }
+
+    if(comma != ','){
+        cout << "BAD INPUT ,";
+        return istr;
+    }
+
+    if(r_paren != ')'){
+        cout << "BAD INPUT )";
+        return istr;
+    }
+    return istr;
+}
+#endif // #ifndef _2DVECTORH
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/2dvector.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,80 @@
+/*
+ *  2dvector.cpp
+ *  simplespring
+ *
+ *  Created by Robert Tubb on 01/06/2011.
+ *  Copyright 2011 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "2dvector.h"
+
+
+TwoVector::TwoVector(){
+	x = 0.0;
+	y = 0.0;
+	//cout << "def constr set vector to zeros" << endl;
+}
+
+TwoVector::TwoVector(double ax, double ay){
+	x = ax;
+	y = ay;
+	//cout << "spec constr set vector to " << ax << "," << ay << endl;
+}
+
+double TwoVector::norm(){
+	double norm;
+	norm = sqrt(x * x + y * y);
+	return norm;
+	
+}
+
+void TwoVector::setCoord(double ax, double ay){
+	x = ax;
+	y = ay;
+
+}
+
+TwoVector TwoVector::minus(TwoVector otherPoint){
+    TwoVector diff;
+    diff.setCoord(x - otherPoint.x, y - otherPoint.y);
+    return diff;
+}
+
+TwoVector TwoVector::operator-(TwoVector otherPoint){
+    TwoVector diff;
+    diff.setCoord(x - otherPoint.x, y - otherPoint.y);
+    return diff;
+}
+
+TwoVector TwoVector::operator*(TwoVector otherPoint){ // if multiplying two vectors - elementwise
+    TwoVector diff;
+    diff.setCoord(x * otherPoint.x, y * otherPoint.y);
+    return diff;
+}
+
+TwoVector TwoVector::operator*(const double& scalar){
+    TwoVector diff;
+    diff.setCoord(x * scalar, y * scalar);
+    return diff;
+}
+
+TwoVector TwoVector::operator+(TwoVector otherPoint){
+    TwoVector diff;
+    diff.setCoord(otherPoint.x + x, otherPoint.y + y);
+    return diff;
+}
+    
+/*
+TwoVector TwoVector::operator=(TwoVector otherPoint){
+    TwoVector result;
+    result.setCoord(otherPoint.x, otherPoint.y);
+    return result;
+}
+*/
+double TwoVector::distanceTo(TwoVector otherPoint){
+    TwoVector diff;
+    diff.setCoord(otherPoint.x - x, otherPoint.y - y);
+    return diff.norm();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AppCore.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Dan Wilcox <danomatika@gmail.com>
+ *
+ * BSD Simplified License.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * See https://github.com/danomatika/ofxPd for documentation
+ *
+ */
+#pragma once
+
+#include "ofMain.h"
+
+#include "ofxPd.h"
+
+// a namespace for the Pd types
+using namespace pd;
+
+class AppCore : public PdReceiver, public PdMidiReceiver {
+
+	public:
+        string patchName;
+		// main
+		void setup(const int numOutChannels, const int numInChannels,
+				   const int sampleRate, const int ticksPerBuffer);
+		void update();
+		void draw();
+        void exit();
+
+		// do something
+		void playTone(int pitch);
+		
+		// input callbacks
+		void keyPressed(int key);
+		
+		// audio callbacks
+		void audioReceived(float * input, int bufferSize, int nChannels);
+		void audioRequested(float * output, int bufferSize, int nChannels);
+		
+		// pd message receiver callbacks
+		void print(const std::string& message);
+		
+		void receiveBang(const std::string& dest);
+		void receiveFloat(const std::string& dest, float value);
+		void receiveSymbol(const std::string& dest, const std::string& symbol);
+		void receiveList(const std::string& dest, const List& list);
+		void receiveMessage(const std::string& dest, const std::string& msg, const List& list);
+		
+        // pd midi receiver callbacks
+		void receiveNoteOn(const int channel, const int pitch, const int velocity);
+		void receiveControlChange(const int channel, const int controller, const int value);
+		void receiveProgramChange(const int channel, const int value);
+		void receivePitchBend(const int channel, const int value);
+		void receiveAftertouch(const int channel, const int value);
+		void receivePolyAftertouch(const int channel, const int pitch, const int value);
+		
+		void receiveMidiByte(const int port, const int byte);
+		
+		// demonstrates how to manually poll for messages
+		void processEvents();
+		
+		ofxPd pd;
+		vector<float> scopeArray;
+        
+        int midiChan;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AppCore.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2011 Dan Wilcox <danomatika@gmail.com>
+ *
+ * BSD Simplified License.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
+ *
+ * See https://github.com/danomatika/ofxPd for documentation
+ *
+ */
+#include "AppCore.h"
+
+//--------------------------------------------------------------
+void AppCore::setup(const int numOutChannels, const int numInChannels,
+				    const int sampleRate, const int ticksPerBuffer) {
+
+	ofSetFrameRate(60);
+	ofSetVerticalSync(true);
+	//ofSetLogLevel(OF_LOG_VERBOSE);
+	
+	// double check where we are ...
+	cout << ofFilePath::getCurrentWorkingDirectory() << endl;
+	
+	if(!pd.init(numOutChannels, numInChannels, sampleRate, ticksPerBuffer)) {
+		ofLog(OF_LOG_ERROR, "Could not init pd");
+		OF_EXIT_APP(1);
+	}
+    midiChan = 1; // midi channels are 1-16
+	
+	// subscribe to receive source names
+	pd.subscribe("toOF");
+	pd.subscribe("env");
+
+	// add message receiver, disables polling (see processEvents)
+	pd.addReceiver(*this);   // automatically receives from all subscribed sources
+	pd.ignore(*this, "env"); // don't receive from "env"
+    //pd.ignore(*this);             // ignore all sources
+	//pd.receive(*this, "toOF");	// receive only from "toOF"
+	
+    // add midi receiver
+    //pd.addMidiReceiver(*this);  // automatically receives from all channels
+    //pd.ignoreMidi(*this, 1);     // ignore midi channel 1
+    pd.ignoreMidi(*this);        // ignore all channels
+    //pd.receiveMidi(*this, 1);    // receive only from channel 1
+
+	// add the data/pd folder to the search path
+	pd.addToSearchPath("pd");
+
+	// audio processing on
+	pd.start();
+
+	// open patch
+    //patchName = "targetSynth6.pd";
+    patchName = "tweakathon_synth_pulse.pd";
+	Patch patch = pd.openPatch(patchName);
+	cout << patch << endl;
+
+
+}
+
+//--------------------------------------------------------------
+void AppCore::update() {
+	ofBackground(100, 100, 100);
+	
+	// update scope array from pd
+	pd.readArray("scope", scopeArray);
+}
+
+//--------------------------------------------------------------
+void AppCore::draw() {
+
+	// draw scope
+	ofSetColor(0, 255, 0);
+	ofSetRectMode(OF_RECTMODE_CENTER);
+	float x = 0, y = ofGetHeight()/2;
+	float w = ofGetWidth() / (float) scopeArray.size(), h = ofGetHeight()/2;
+	for(int i = 0; i < scopeArray.size()-1; ++i) {
+		ofLine(x, y+scopeArray[i]*h, x+w, y+scopeArray[i+1]*h);
+		x += w;
+	}
+}
+
+//--------------------------------------------------------------
+void AppCore::exit() {
+    pd.stop();
+}
+
+//--------------------------------------------------------------
+void AppCore::playTone(int pitch) {
+	pd << StartMessage() << "pitch" << pitch << FinishList("tone") << Bang("tone");
+}
+
+//--------------------------------------------------------------
+void AppCore::keyPressed (int key) {
+
+	switch(key) {
+	
+		case 'a':
+			playTone(60);
+			break;
+		case 'w':
+			playTone(61);
+			break;
+		case 's':
+			playTone(62);
+			break;
+		case 'e':
+			playTone(63);
+			break;
+		case 'd':
+			playTone(64);
+			break;
+		case 'f':
+			playTone(65);
+			break;
+		case 't':
+			playTone(66);
+			break;
+		case 'g':
+			playTone(67);
+			break;
+		case 'y':
+			playTone(68);
+			break;
+		case 'h':
+			playTone(69);
+			break;
+		case 'u':
+			playTone(70);
+			break;
+		case 'j':
+			playTone(71);
+			break;
+		case 'k':
+			playTone(72);
+			break;
+			
+		case ' ':
+			if(pd.isReceiving(*this, "env")) {
+				pd.ignore(*this, "env");
+                cout << "ignoring env" << endl;
+			}
+			else {
+				pd.receive(*this, "env");
+                cout << "receiving from env" << endl;
+			}
+			break;
+			
+		default:
+			break;
+	}
+}
+
+//--------------------------------------------------------------
+void AppCore::audioReceived(float * input, int bufferSize, int nChannels) {
+	pd.audioIn(input, bufferSize, nChannels);
+}
+
+//--------------------------------------------------------------
+void AppCore::audioRequested(float * output, int bufferSize, int nChannels) {
+	pd.audioOut(output, bufferSize, nChannels);
+}
+
+//--------------------------------------------------------------
+void AppCore::print(const std::string& message) {
+	cout << message << endl;
+}
+
+//--------------------------------------------------------------		
+void AppCore::receiveBang(const std::string& dest) {
+	cout << "OF: bang " << dest << endl;
+}
+
+void AppCore::receiveFloat(const std::string& dest, float value) {
+	cout << "OF: float " << dest << ": " << value << endl;
+}
+
+void AppCore::receiveSymbol(const std::string& dest, const std::string& symbol) {
+	cout << "OF: symbol " << dest << ": " << symbol << endl;
+}
+
+void AppCore::receiveList(const std::string& dest, const List& list) {
+	cout << "OF: list " << dest << ": ";
+	
+	// step through the list
+	for(int i = 0; i < list.len(); ++i) {
+		if(list.isFloat(i))
+			cout << list.getFloat(i) << " ";
+		else if(list.isSymbol(i))
+			cout << list.getSymbol(i) << " ";
+	}
+    
+    // you can also use the built in toString function or simply stream it out
+    // cout << list.toString();
+    // cout << list;
+	
+    // print an OSC-style type string
+	cout << list.types() << endl;
+}
+
+void AppCore::receiveMessage(const std::string& dest, const std::string& msg, const List& list) {
+	cout << "OF: message " << dest << ": " << msg << " " << list.toString() << list.types() << endl;
+}
+
+//--------------------------------------------------------------
+void AppCore::receiveNoteOn(const int channel, const int pitch, const int velocity) {
+	cout << "OF MIDI: note on: " << channel << " " << pitch << " " << velocity << endl;
+}
+
+void AppCore::receiveControlChange(const int channel, const int controller, const int value) {
+	cout << "OF MIDI: control change: " << channel << " " << controller << " " << value << endl;
+}
+
+// note: pgm nums are 1-128 to match pd
+void AppCore::receiveProgramChange(const int channel, const int value) {
+	cout << "OF MIDI: program change: " << channel << " " << value << endl;
+}
+
+void AppCore::receivePitchBend(const int channel, const int value) {
+	cout << "OF MIDI: pitch bend: " << channel << " " << value << endl;
+}
+
+void AppCore::receiveAftertouch(const int channel, const int value) {
+	cout << "OF MIDI: aftertouch: " << channel << " " << value << endl;
+}
+
+void AppCore::receivePolyAftertouch(const int channel, const int pitch, const int value) {
+	cout << "OF MIDI: poly aftertouch: " << channel << " " << pitch << " " << value << endl;
+}
+
+// note: pd adds +2 to the port num, so sending to port 3 in pd to [midiout],
+//       shows up at port 1 in ofxPd
+void AppCore::receiveMidiByte(const int port, const int byte) {
+	cout << "OF MIDI: midi byte: " << port << " " << byte << endl;
+}
+
+//--------------------------------------------------------------
+void AppCore::processEvents() {
+	
+	cout << "Number of waiting messages: " << pd.numMessages() << endl;
+	
+	while(pd.numMessages() > 0) {
+		Message& msg = pd.nextMessage();
+
+		switch(msg.type) {
+			
+			case pd::PRINT:
+				cout << "OF: " << msg.symbol << endl;
+				break;
+			
+			// events
+			case pd::BANG:
+				cout << "OF: bang " << msg.dest << endl;
+				break;
+			case pd::FLOAT:
+				cout << "OF: float " << msg.dest << ": " << msg.num << endl;
+				break;
+			case pd::SYMBOL:
+				cout << "OF: symbol " << msg.dest << ": " << msg.symbol << endl;
+				break;
+			case pd::LIST:
+				cout << "OF: list " << msg.list << msg.list.types() << endl;
+				break;
+			case pd::MESSAGE:
+				cout << "OF: message " << msg.dest << ": " << msg.symbol << " " 
+					 << msg.list << msg.list.types() << endl;
+				break;
+			
+			// midi
+			case pd::NOTE_ON:
+				cout << "OF MIDI: note on: " << msg.channel << " "
+					 << msg.pitch << " " << msg.velocity << endl;
+				break;
+			case pd::CONTROL_CHANGE:
+				cout << "OF MIDI: control change: " << msg.channel
+					 << " " << msg.controller << " " << msg.value << endl;
+				break;
+			case pd::PROGRAM_CHANGE:
+				cout << "OF MIDI: program change: " << msg.channel << " "
+					 << msg.value << endl;
+				break;
+			case pd::PITCH_BEND:
+				cout << "OF MIDI: pitch bend: " << msg.channel << " "
+					 << msg.value << endl;
+				break;
+			case pd::AFTERTOUCH:
+				cout << "OF MIDI: aftertouch: " << msg.channel << " "
+					 << msg.value << endl;
+				break;
+			case pd::POLY_AFTERTOUCH:
+				cout << "OF MIDI: poly aftertouch: " << msg.channel << " "
+					 << msg.pitch << " " << msg.value << endl;
+				break;
+			case pd::BYTE:
+				cout << "OF MIDI: midi byte: " << msg.port << " 0x"
+					 << hex << (int) msg.byte << dec << endl;
+				break;
+		
+			case pd::NONE:
+				cout << "OF: NONE ... empty message" << endl;
+				break;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HelpViewController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,16 @@
+//
+//  HelpViewController.h
+//  sonicZoom
+//
+//  Created by Robert Tubb on 01/02/2013.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface HelpViewController : UIViewController
+@property (nonatomic, assign)       id theOFAppRef;
+-(IBAction)hide:(id)sender;
+-(IBAction)show:(id)sender;
+-(void)setAppRef:(id)theOFApp;
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HelpViewController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,53 @@
+//
+//  HelpViewController.m
+//  sonicZoom
+//
+//  Created by Robert Tubb on 01/02/2013.
+//
+//
+
+#import "HelpViewController.h"
+#import "testApp.h"
+@interface HelpViewController ()
+
+@end
+
+@implementation HelpViewController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        // Custom initialization
+    }
+    return self;
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    // Do any additional setup after loading the view from its nib.
+}
+
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];
+    // Dispose of any resources that can be recreated.
+}
+
+- (void)setAppRef:(id)theOFApp{
+    self.theOFAppRef = theOFApp;
+    
+}
+-(IBAction)show:(id)sender{
+    self.view.hidden = NO;
+}
+
+- (IBAction)hide:(id)sender
+{
+    self.view.hidden = YES;
+    ((testApp *)self.theOFAppRef)->helpHidden();
+
+   
+}
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HelpViewController.xib	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
+	<data>
+		<int key="IBDocument.SystemTarget">1552</int>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			<string key="NS.object.0">2083</string>
+		</object>
+		<array key="IBDocument.IntegratedClassDependencies">
+			<string>IBProxyObject</string>
+			<string>IBUIButton</string>
+			<string>IBUILabel</string>
+			<string>IBUIView</string>
+		</array>
+		<array key="IBDocument.PluginDependencies">
+			<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+		</array>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<object class="IBProxyObject" id="841351856">
+				<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+			<object class="IBProxyObject" id="606714003">
+				<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+			<object class="IBUIView" id="766721923">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">292</int>
+				<array class="NSMutableArray" key="NSSubviews">
+					<object class="IBUIButton" id="519426224">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{319, 941}, {130, 44}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<int key="IBUIContentHorizontalAlignment">0</int>
+						<int key="IBUIContentVerticalAlignment">0</int>
+						<int key="IBUIButtonType">1</int>
+						<string key="IBUINormalTitle">BACK TO APP</string>
+						<object class="NSColor" key="IBUIHighlightedTitleColor">
+							<int key="NSColorSpace">3</int>
+							<bytes key="NSWhite">MQA</bytes>
+						</object>
+						<object class="NSColor" key="IBUINormalTitleColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
+						</object>
+						<object class="NSColor" key="IBUINormalTitleShadowColor">
+							<int key="NSColorSpace">3</int>
+							<bytes key="NSWhite">MC41AA</bytes>
+						</object>
+						<object class="IBUIFontDescription" key="IBUIFontDescription">
+							<int key="type">2</int>
+							<double key="pointSize">15</double>
+						</object>
+						<object class="NSFont" key="IBUIFont">
+							<string key="NSName">Helvetica-Bold</string>
+							<double key="NSSize">15</double>
+							<int key="NSfFlags">16</int>
+						</object>
+					</object>
+					<object class="IBUILabel" id="623791900">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{64, 53}, {640, 872}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="519426224"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<bool key="IBUIClipsSubviews">YES</bool>
+						<int key="IBUIContentMode">7</int>
+						<bool key="IBUIUserInteractionEnabled">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<string type="base64-UTF8" key="IBUIText">SEVMUOKAqOKAqOKAqEkgbmVlZCBzb21lb25lLiBOb3QganVzdCBhbnlvbmUuDQ</string>
+						<object class="NSColor" key="IBUITextColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MCAxIDAuOTc2NDI2Mjc5OAA</bytes>
+						</object>
+						<nil key="IBUIHighlightedColor"/>
+						<int key="IBUIBaselineAdjustment">0</int>
+						<int key="IBUINumberOfLines">300</int>
+						<object class="IBUIFontDescription" key="IBUIFontDescription">
+							<int key="type">1</int>
+							<double key="pointSize">16</double>
+						</object>
+						<object class="NSFont" key="IBUIFont">
+							<string key="NSName">Helvetica</string>
+							<double key="NSSize">16</double>
+							<int key="NSfFlags">16</int>
+						</object>
+						<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+						<double key="preferredMaxLayoutWidth">640</double>
+					</object>
+				</array>
+				<string key="NSFrameSize">{1024, 768}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSWindow"/>
+				<reference key="NSNextKeyView" ref="623791900"/>
+				<object class="NSColor" key="IBUIBackgroundColor">
+					<int key="NSColorSpace">1</int>
+					<bytes key="NSRGB">MCAwIDAAA</bytes>
+				</object>
+				<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+				<object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
+					<int key="IBUIInterfaceOrientation">3</int>
+					<int key="interfaceOrientation">3</int>
+				</object>
+				<object class="IBUIScreenMetrics" key="IBUISimulatedDestinationMetrics">
+					<string key="IBUISimulatedSizeMetricsClass">IBUIScreenMetrics</string>
+					<object class="NSMutableDictionary" key="IBUINormalizedOrientationToSizeMap">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<array key="dict.sortedKeys">
+							<integer value="1"/>
+							<integer value="3"/>
+						</array>
+						<array key="dict.values">
+							<string>{768, 1024}</string>
+							<string>{1024, 768}</string>
+						</array>
+					</object>
+					<string key="IBUITargetRuntime">IBIPadFramework</string>
+					<string key="IBUIDisplayName">iPad Full Screen</string>
+					<int key="IBUIType">1</int>
+				</object>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+		</array>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<array class="NSMutableArray" key="connectionRecords">
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="766721923"/>
+					</object>
+					<int key="connectionID">3</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="519426224"/>
+						<reference key="destination" ref="841351856"/>
+						<int key="IBEventType">7</int>
+					</object>
+					<int key="connectionID">24</int>
+				</object>
+			</array>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<array key="orderedObjects">
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<array key="object" id="0"/>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="841351856"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="606714003"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="766721923"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="519426224"/>
+							<reference ref="623791900"/>
+						</array>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="519426224"/>
+						<array class="NSMutableArray" key="children"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">26</int>
+						<reference key="object" ref="623791900"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+				</array>
+			</object>
+			<dictionary class="NSMutableDictionary" key="flattenedProperties">
+				<string key="-1.CustomClassName">HelpViewController</string>
+				<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="-2.CustomClassName">UIResponder</string>
+				<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="26.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			</dictionary>
+			<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+			<nil key="activeLocalization"/>
+			<dictionary class="NSMutableDictionary" key="localizations"/>
+			<nil key="sourceID"/>
+			<int key="maxID">26</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<array class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<object class="IBPartialClassDescription">
+					<string key="className">HelpViewController</string>
+					<string key="superclassName">UIViewController</string>
+					<dictionary class="NSMutableDictionary" key="actions">
+						<string key="hide:">id</string>
+						<string key="show:">id</string>
+					</dictionary>
+					<dictionary class="NSMutableDictionary" key="actionInfosByName">
+						<object class="IBActionInfo" key="hide:">
+							<string key="name">hide:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+						<object class="IBActionInfo" key="show:">
+							<string key="name">show:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+					</dictionary>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/HelpViewController.h</string>
+					</object>
+				</object>
+			</array>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<string key="IBCocoaTouchPluginVersion">2083</string>
+	</data>
+</archive>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IntroViewController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,20 @@
+//
+//  IntroViewController.h
+//  sonicZoom
+//
+//  Created by Robert Tubb on 29/01/2013.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+@interface IntroViewController : UIViewController
+
+@property (nonatomic, assign)       id theOFAppRef;
+@property (retain, nonatomic) IBOutlet UILabel *text;
+
+-(IBAction)hide:(id)sender;
+-(IBAction)show:(id)sender;
+-(IBAction)disagree:(id)sender;
+-(void)setAppRef:(id)theOFApp;
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IntroViewController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,68 @@
+//
+//  IntroViewController.m
+//  sonicZoom
+//
+//  Created by Robert Tubb on 29/01/2013.
+//
+//
+
+#import "IntroViewController.h"
+#import "testApp.h"
+@interface IntroViewController ()
+
+@end
+
+@implementation IntroViewController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        // Custom initialization
+    }
+    return self;
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    // Do any additional setup after loading the view from its nib.
+}
+
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];
+    // Dispose of any resources that can be recreated.
+}
+
+- (void)setAppRef:(id)theOFApp{
+    self.theOFAppRef = theOFApp;
+    
+}
+
+- (IBAction)show:(id)sender
+{
+    self.theOFAppRef = sender;
+    self.view.hidden = NO;
+}
+- (IBAction)hide:(id)sender
+{
+    self.view.hidden = YES;
+    ((testApp *)self.theOFAppRef)->introHidden();
+    
+}
+- (IBAction)disagree:(id)sender
+{
+    // shut down the app
+    self.view.hidden = YES;
+    ((testApp *)self.theOFAppRef)->introHidden();
+}
+- (void)dealloc {
+    [_text release];
+    [super dealloc];
+}
+- (void)viewDidUnload {
+    [self setText:nil];
+    [super viewDidUnload];
+}
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IntroViewController.xib	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="3.0" toolsVersion="4514" systemVersion="12F45" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none">
+    <dependencies>
+        <deployment defaultVersion="1280" identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="IntroViewController">
+            <connections>
+                <outlet property="text" destination="14" id="57"/>
+                <outlet property="view" destination="2" id="3"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="2">
+            <rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <subviews>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="4">
+                    <rect key="frame" x="454" y="643" width="116" height="44"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    <state key="normal" title="AGREE" backgroundImage="buttron.png">
+                        <color key="titleColor" red="0.28581259671449843" green="0.80918817934782605" blue="0.73026968770868927" alpha="1" colorSpace="calibratedRGB"/>
+                        <color key="titleShadowColor" red="0.0" green="0.79530400815217395" blue="0.77655573399798061" alpha="1" colorSpace="calibratedRGB"/>
+                    </state>
+                    <connections>
+                        <action selector="hide:" destination="-1" eventType="touchUpInside" id="55"/>
+                    </connections>
+                </button>
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" lineBreakMode="tailTruncation" numberOfLines="39" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="14">
+                    <rect key="frame" x="158" y="-139" width="773" height="735"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    <mutableString key="text">Welcome to the "Tweakathon". This will test your ability to tweak the controls of a synthesiser to achieve a desired sound. Your task is to find a sound that matches a target sound as accurately and as quickly as possible, using a variety of different control methods. The target and you current sound will play repeatedly. The second sound changes as you tweak the controls. When you match the sounds as well as you can, press submit. You will then see how far you were from the correct settings, and be given a score based on the time you took and how far away from the target you were. 
There will be more and more controls as the test progresses, therefore it will become harder to find the target sound. You actions will be logged and sent to a server at Queen Mary University for analysis. If you agree to this, click "Agree" button to start the test.</mutableString>
+                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                    <color key="textColor" red="0.72194573409571561" green="1" blue="0.83094137152153613" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="TWEAKATHON" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="50">
+                    <rect key="frame" x="451" y="50" width="134" height="24"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    <fontDescription key="fontDescription" type="system" pointSize="20"/>
+                    <color key="textColor" red="0.33826699840000002" green="0.9053322399" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" cocoaTouchSystemColor="darkTextColor"/>
+            <simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
+            <simulatedScreenMetrics key="simulatedDestinationMetrics"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="buttron.png" width="150" height="60"/>
+    </resources>
+</document>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MessageOrganiser.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,699 @@
+//
+//  MessageOrganiser.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/12/2013.
+//
+// This object handles the mapping from GUI to params
+//
+// and sends their messages to PD and eventLogger
+#pragma once
+#include "eventLogger.h"
+#include <map.h>
+#include <vector>
+#include <string>
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+
+#include <UIElement.h>
+#include <Buttron.h>
+#include <ButtronSlider.h>
+#include <ButtronXY.h>
+#include "AppCore.h"
+#include "ofxPd.h"
+#include "TestController.h"
+#include "timeController.h"
+#include "PDSynthWrapper.h"
+#include "ofxTimer.h"
+#include "sliderPanel.h"
+//#include "testApp.h"
+#include "targetSymbol.h"
+#include "3Dbox.h"
+#include "TextPanel.h"
+#include "CountdownText.h"
+#include "buttonPanel.h"
+
+// event logger needs to know
+// which controls were showing in what mode
+// which controls were mapped to what param
+// what was the target sound params
+// all the updates of control movements, submit, quit etc
+
+// this is the bit that handles mapping from UI elements to synth i.e testApp DOESNT DO THAT
+
+// has links to panel sliders can show hide them
+
+// controls flow of stuff
+
+//---------------------------------------------------------------------
+//---------------------------------------------------------------------
+extern TimeController timeController;
+
+extern EventLogger eventLogger;
+
+typedef boost::function<void(void)> AppModeChangeFunction;
+
+class MessageOrganiser {
+private:
+    AppCore* core;
+    //testApp* theOFApp;
+    PDSynthWrapper targetSynth;
+    PDSynthWrapper candidateSynth;
+
+    map<int,UIElement*> currentMapping; // could get more sophisticated if not 1-1 ?
+    
+    SliderPanel* panel;
+    TimeController altPlaybackController;
+    
+    TestController* testController;
+    Buttron* newTestButton;
+    //Buttron* submitButton;
+    
+    ButtonPanel* bottomPanel; // shows during test : play buttons and submit
+    Buttron* targetPlayButton; // so we can hide target in memory test. this pointer stuff is getting out of hand
+    CountdownText* countdownPanel;
+    TargetSymbol* targetSymbol;
+    Leap3DBoxGL* box3D;
+    TextPanel* scorePanel;
+    TextPanel* finishPanel;
+    AppModeChangeFunction testAppModeChange;
+    
+    //int scoreRunningTotal;
+    TimerID currentSoundPlayTimer;
+    
+    int alternationSpeed; // ms between cand and target
+    bool playingAlternating;
+    
+    bool okToGetLeapMidi;
+
+    void testsFinished(){
+        panel->hide();
+        bottomPanel->hide();
+        newTestButton->hide();
+        
+        vector<int> eData;
+        eData.push_back(testController->getScoreRunningTotal());
+        eventLogger.logEvent(ALL_TESTS_COMPLETED, eData);
+        
+        // TODO set final score screen txt to testController->getScoreRunningTotal()
+        finishPanel->show();
+        
+        string user = eventLogger.getUsername();
+        stringstream s;
+        s << "Experiment completed"
+            << endl << endl
+            << "You scored: " << testController->getScoreRunningTotal() << " well done " << user << endl << endl
+            << "to retake test please close " << endl << endl
+             <<   "the app and restart with username<num test>";
+        finishPanel->setText(s.str());
+        // get test app to do something...
+        
+        eventLogger.saveSessionToFile();
+    };
+    
+    void setupNewTest(){
+        // get mapping for new test and make sure we have right controls and stuff
+
+        
+        Test newTest = testController->goToNextTest();
+        
+        // V0.2 put details about what kind of test it is
+        vector<int> eData;
+        eData.push_back(newTest.isPractice());
+        eData.push_back(newTest.isWithHint());
+        eData.push_back(newTest.isMemoryTest());
+        eventLogger.logEvent(NEW_TEST, eData);
+        
+        
+        vector<int> mappingIDsForChangeableParams = setSynthsUpForNewTest(newTest);
+        
+        vector<UIElement*> UIElemHandles = panel->generateControls(testController->getCurrentListOfControls(), testController->getCurrentPanelType());
+        
+        mapUIToNewTestParams(UIElemHandles, mappingIDsForChangeableParams);
+        
+        countdownPanel->setTestTypeString(newTest.getTestTypeAdvanceWarning());
+        
+
+    };
+    void startNewTest(){
+        Test t = testController->getCurrentTest();
+        
+        countdownPanel->hide();
+        panel->show();
+        panel->setActive(true);
+        if(t.isWithHint()){
+            panel->showHint(true);
+        }
+        
+        bottomPanel->show();
+        targetPlayButton->show(); // incase it was memory test
+        if (t.isMemoryTest()){
+            targetPlayButton->setLabel("Memorise!");
+        }else{
+            targetPlayButton->setLabel("Target");
+        }
+        //startAlternatingPlayback();
+        //timeController.scheduleEvent(boost::bind(&MessageOrganiser::sendSynthValuesAgain, this), 200);
+        timeController.startStopwatch();
+        eventLogger.logEvent(TEST_TIMER_STARTED);
+        
+        
+        if(t.getListOfControlTypes()[0] == LEAP3D){
+            okToGetLeapMidi = true;
+        }
+    };
+    
+    vector<int> setSynthsUpForNewTest(Test newTest){
+        targetSynth.setAllParams(newTest.getTargetValues());
+        eventLogger.logEvent(TARGET_PARAM_SET, newTest.getTargetValues()); // unless something goes wrong in setAllParams
+        
+        candidateSynth.setAllParams(newTest.getStartingCandidateValues());
+        eventLogger.logEvent(CANDIDATE_PARAM_SET,newTest.getStartingCandidateValues());
+        
+        // eventLogger.logEvent(NEW_TARGET_PARAMS, vector<int> );
+        // eventLogger.logEvent(NEW_CANDIDATE_PARAMS, vector<int> );
+        
+        vector<int> mids = candidateSynth.getMappingIDForIndices(newTest.getChangeableIndices());
+        
+        eventLogger.logEvent(CANDIDATE_CHANGEABLE_IDX, newTest.getChangeableIndices());
+        eventLogger.logEvent(CANDIDATE_MAPPING_IDS, mids);
+        
+        return mids;
+    };
+    void sendSynthValuesAgain(){
+        candidateSynth.sendAllParams();
+        targetSynth.sendAllParams();
+    };
+    
+    // could have been cleverer. takes forever due to searching ???
+    void mapUIToNewTestParams(vector<UIElement*> elems, vector<int> mids){
+        
+        vector<UIElement*>::iterator elit;
+        vector<int> typeListLog;
+        int i = 0;
+        for(elit=elems.begin(); elit<elems.end();elit++){
+            if ( (*elit)->getType() == XYPAD){
+                if(i+1 >= mids.size()){
+                    cout << "ERROR ERROR: too many controls for mapping IDs" << endl;
+                }
+                
+                ButtronXY* theXY = (ButtronXY*)(*elit);
+                mapXYToParams(theXY, mids[i], mids[i+1]);
+                theXY->setValueAndScale(candidateSynth.getParamValueForID(mids[i]), candidateSynth.getParamValueForID(mids[i+1]));
+                theXY->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i]))
+                                    ,targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i+1])));
+                i+=2;
+                typeListLog.push_back(int(XYPAD));
+            }else if ( (*elit)->getType() == SLIDER){
+                if(i >= mids.size()){
+                    cout << "ERROR ERROR: too many controls for mapping IDs" << endl;
+                }
+                
+                ButtronSlider* theSlider = (ButtronSlider*)(*elit);
+                mapControlToParam((*elit), mids[i]);
+                theSlider->setValueAndScale(candidateSynth.getParamValueForID(mids[i]));
+                cout << "Hint Value " << targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) << endl;
+                theSlider->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])));
+                i++;
+                typeListLog.push_back(int(SLIDER));
+            }else if ( (*elit)->getType() == LEAP3D ){
+                set3Dbox((Leap3DBoxGL*)(*elit));
+                // UH
+                string nameX = candidateSynth.getNameForMappingID(mids[i]);
+                box3D->setHintValue(0,targetSynth.getParamValueFromName(nameX));
+                box3D->setValueAndScale(0, candidateSynth.getParamValueForID(mids[i]));
+                i++;
+                
+                string nameY = candidateSynth.getNameForMappingID(mids[i]);
+                box3D->setHintValue(1,targetSynth.getParamValueFromName(nameY));
+                box3D->setValueAndScale(1, candidateSynth.getParamValueForID(mids[i]));
+                i++;
+                
+                string nameZ = candidateSynth.getNameForMappingID(mids[i]);
+                box3D->setHintValue(2,targetSynth.getParamValueFromName(nameZ));
+                box3D->setValueAndScale(2, candidateSynth.getParamValueForID(mids[i]));
+                i++;
+                
+
+                box3D->setLabels(nameX,nameY,nameZ);
+                typeListLog.push_back(int(LEAP3D));
+                
+            }else{
+                cout << "ERROR ERROR: ui type not handled my mapping function !" << endl;
+            }
+        }
+        
+        eventLogger.logEvent(CONTROL_LIST,typeListLog);
+    };
+    
+    // TODO - no, triggering playback needs to be logged
+    void startAlternatingPlayback(){
+        
+        cout << "start alt playback" << endl;
+        // use our special timer to fire off play to pd
+        // sets off timed alternating playback
+        
+        playAlternating();
+        playingAlternating = true;
+
+    };
+    void stopAlternatingPlayback(){
+        cout << "stop alt playback" << endl;
+        // kill the alternation
+        timeController.cancelEvent(currentSoundPlayTimer);
+        playingAlternating = false;
+    };
+    
+    void playAlternating(){
+        
+        static bool alt;
+        int nextTime;
+        if (alt){
+            targetSynth.trigger();
+            // flash the target thingy
+            targetSymbol->flash();
+            nextTime = alternationSpeed*1.503; // gap after target
+        }else{
+            sendSynthValuesAgain(); // and again and again
+            candidateSynth.trigger();
+            panel->flash();
+            nextTime = alternationSpeed;
+        }
+        alt = !alt;
+        candidateSynth.setNoteLength(alternationSpeed);
+        targetSynth.setNoteLength(alternationSpeed); // could be user alterable
+        currentSoundPlayTimer = timeController.scheduleEvent(boost::bind(&MessageOrganiser::playAlternating,this), nextTime);
+        
+        
+        
+    };
+    
+    void delayedShowNewTest(){
+        newTestButton->show();
+        // JUST IN CASE IT CRASHES near end...
+        //eventLogger.saveSessionToFile();
+    };
+    void submitSingleControl(){
+        // if last one
+        // submitPressed()
+        
+        // else
+        
+        // grey out that slider,
+        // activate next slider and show it's button (same button but moved!???)
+        
+    };
+    
+    
+    void submitPressed(){
+        
+        // depending on mode go to next control
+        //        if(testController->getCurrentPanelType() == SEQUENTIAL){
+        //            submitSingleControl();
+        //            return;
+        //        }
+        // otherwise do this other  - or call
+        
+        okToGetLeapMidi = false;
+        
+        TimerMillisec timeTaken = timeController.stopStopwatch();
+        vector<int> answer = candidateSynth.getAllParamValues();
+        
+        eventLogger.logEvent(SUBMIT_PRESSED, answer); //, answer, scoreRunningTotal, time taken (why not?));
+        
+        TestResult result = testController->submitAnswer(answer, timeTaken); // TODO returns all the results
+        
+        vector<int> logResult;
+        logResult.push_back(result.realDistanceToTarget*1000); // measured in milliCC !??!
+        logResult.push_back(result.timeTaken); // milliseconds
+        logResult.push_back(result.score);
+        logResult.push_back(result.targetBandHit);
+        logResult.push_back(result.timeWindowHit);
+        
+        eventLogger.logEvent(DISTANCE_TIME_SCORE, logResult);
+        
+        
+        // gui stuff - different controller?
+        panel->setActive(false);
+        panel->showHint(true); // add some encouraging feedback to hint
+        bottomPanel->hide();
+        
+        showScoreForTest(result);
+        
+        stopAlternatingPlayback();
+        
+        // was it the final sumbit?
+        if(testController->isLastTest()){
+            // thats it - show a final score screen etc
+            timeController.scheduleEvent(boost::bind(&MessageOrganiser::testsFinished, this), 500);
+            return;
+        }else{
+            timeController.scheduleEvent(boost::bind(&MessageOrganiser::delayedShowNewTest, this), 300);
+        }
+        
+
+    };
+    
+    void showScoreForTest(TestResult result){
+        scorePanel->setText(result.displayText);
+        scorePanel->show();
+        
+        ofColor c;
+        if(result.targetBandHit == 1){
+            // yellow red blue
+            c = ofColor(255,255,0,255);
+        }else if(result.targetBandHit == 2){
+            c = ofColor(255,0,0,255);
+        }else if(result.targetBandHit == 3){
+            c = ofColor(45,45,255,255);
+        }else if(result.targetBandHit == 4){
+            c = ofColor(0,255,0,255);
+        }else{
+            c = ofColor(150,235,200,255);
+        }
+        scorePanel->setColor(c);
+        panel->setHintColor(c);
+    };
+    
+    // we want to set UI object
+    void setUIToParam(int index, int value){ // e.g. from MIDI incoming, will handle both box and sliders...
+        // theXY->setValueAndScale(candidateSynth.getParamValueForID(mids[i]), candidateSynth.getParamValueForID(mids[i+1]));
+        UIElement* elem;
+        // get the element
+        if(panel->subElements.size() <= index){
+            return;
+        }
+        elem = panel->subElements[index];
+        if ( elem->getType() == SLIDER){
+            ButtronSlider* theSlider = (ButtronSlider*)elem;
+            theSlider->setValueAndScale(value);
+            
+        }else{
+            cout << "ERROR ERROR: ui type not handled by setUIToParam!" << endl;
+        }
+        
+    };
+    
+    
+    void mapControlToParam(UIElement* control, int mappingID){
+        
+        UICallbackFunction callbackF;
+        callbackF = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
+        control->addHandler(callbackF, mappingID);
+        // put in our map so we can send param values to gui
+        currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
+        cout << " Mapped control to ID: " << mappingID << "Name: " << candidateSynth.getNameForMappingID(mappingID) << endl;
+        control->setLabel(candidateSynth.getNameForMappingID(mappingID));
+    };
+    
+    void mapXYToParams(ButtronXY* control, int mappingIDX, int mappingIDY){
+        UICallbackFunction callback;
+        
+        callback = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
+        
+        control->addHandler(callback, mappingIDX, mappingIDY);
+        
+        // put in our map so we can send param values to gui
+        //currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
+        
+        
+        cout << " Mapped control to XID: " << mappingIDX << "Name: " << candidateSynth.getNameForMappingID(mappingIDX) << endl;
+        cout << " Mapped control to YID: " << mappingIDY << "Name: " << candidateSynth.getNameForMappingID(mappingIDY) << endl;
+        control->setLabel(candidateSynth.getNameForMappingID(mappingIDX), candidateSynth.getNameForMappingID(mappingIDY));
+        
+    };
+    
+    void mapLeapToParams(ButtronXY* control, int mappingIDX, int mappingIDY, int mappingIDZ){
+//        UICallbackFunction callbackX;
+//        UICallbackFunction callbackY;
+//        UICallbackFunction callbackZ;
+//        
+//        callbackX = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
+//        callbackY = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
+//        callbackZ = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
+//        
+//        control->addHandler(callbackX, mappingIDX);
+//        control->addHandler(callbackY, mappingIDY);
+//        
+//        // put in our map so we can send param values to gui
+//        //currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
+//        
+//        
+//        cout << " Mapped control to XID: " << mappingIDX << "Name: " << candidateSynth.getNameForMappingID(mappingIDX) << endl;
+//        cout << " Mapped control to YID: " << mappingIDY << "Name: " << candidateSynth.getNameForMappingID(mappingIDY) << endl;
+//        control->setLabel(candidateSynth.getNameForMappingID(mappingIDX), candidateSynth.getNameForMappingID(mappingIDY));
+        
+    };
+    
+    void mapControlToParam(UIElement* control, string paramName){
+        // get mapping ID from synth
+        int mappingID = candidateSynth.getMappingIDForName(paramName);
+        mapControlToParam(control, mappingID);
+        control->setLabel(paramName);
+    };
+public:
+    void init(AppCore* aCore, TestController* tc){
+        // set PD core...
+
+        core = aCore;
+        targetSynth.init(aCore,"targetSynth");
+        candidateSynth.init(aCore,"candidateSynth");
+        
+        testController = tc;
+        currentSoundPlayTimer = -1;
+        okToGetLeapMidi = false;
+        
+        alternationSpeed = 200;
+        
+        candidateSynth.setNoteLength(alternationSpeed);
+        targetSynth.setNoteLength(alternationSpeed); 
+        
+        playingAlternating = false;
+    };
+    void setNewTestButton(Buttron * ntb){
+        newTestButton = ntb;
+    };
+    void set3Dbox(Leap3DBoxGL* box){
+        box3D = box;
+    };
+    void setBottomPanel(ButtonPanel * ntb){
+        bottomPanel = ntb;
+    };
+    void setControlPanel(SliderPanel* p){
+        panel = p;
+        
+    };
+    void setCountdownPanel(CountdownText* cd){
+        countdownPanel = cd;
+    };
+    void setTargetSymbol(TargetSymbol* ts){
+        targetSymbol = ts;
+    };
+    void setScorePanel(TextPanel* tp){
+        scorePanel = tp;
+    };
+    void setFinishPanel(TextPanel* fp){
+        finishPanel = fp;
+    }
+    void setTargetButton(Buttron* tb){
+        targetPlayButton = tb;
+    }
+    int getScore(){
+        return testController->getScoreRunningTotal();
+    };
+    
+    pair<int,int> getTime(){
+        TimerMillisec tms = timeController.getStopwatchElapsedTime();
+        int s = int(tms/1000);
+        int hs = int((tms%1000)/10);
+        pair<int,int> p(s,hs);
+        return p;
+    };
+    void countdownToNewTest(){
+        
+        panel->hide();
+        panel->setActive(false);
+        scorePanel->hide();
+        bottomPanel->hide();
+        newTestButton->hide();
+        
+        // set up stuff
+        setupNewTest();
+        eventLogger.logEvent(COUNTDOWN_INITIATED);
+        
+        countdownPanel->showAndStart(3);
+
+        timeController.scheduleEvent(boost::bind(&MessageOrganiser::startNewTest, this), 3000);
+
+    };
+    void sendToGUI(vector<int> paramsToMap){
+        // look up these ids in mapping table
+    };
+    void saveGoodTest(Test t){
+        
+    };
+    void playTargetButtonPressed(){
+
+        static int numPlays = 3;
+        
+        Test* t = testController->getCurrentTestPtr();
+        if (!t->checkTargetPlaysRemaining()){
+                cout << t->getTargetPlaysLeft() << endl;
+            
+                sendSynthValuesAgain();
+                targetSynth.trigger();
+                eventLogger.logEvent(TARGET_PLAYED);
+                targetPlayButton->hide();
+                return;
+
+        }
+        cout << t->getTargetPlaysLeft() << endl;
+        
+        sendSynthValuesAgain();
+        targetSynth.trigger();
+        eventLogger.logEvent(TARGET_PLAYED);
+        
+        return;
+    }
+    void playCandidateButtonPressed(){
+        //
+    }
+    void buttonPressCallback(int mappingID, int value){
+        if(mappingID == VOLUME_CHANGE_ID){
+            targetSynth.sendVolume(value);
+            candidateSynth.sendVolume(value);
+            
+        }
+        if(mappingID == SPEED_CHANGE_ID){
+            alternationSpeed = 2*(140 - value);
+            vector<int> eData;
+            eData.push_back(alternationSpeed);
+            eventLogger.logEvent(SPEED_CHANGED, eData);
+        }
+        if(mappingID == NEW_TEST_ID){
+            countdownToNewTest();
+            return;
+        }
+        if (mappingID == START_ALTERNATE_ID){
+            if(!playingAlternating){
+                startAlternatingPlayback();
+                
+            }else{
+                stopAlternatingPlayback();
+            }
+            return;
+        }
+        if(mappingID == GOOD_TEST_ID){
+            Test t = testController->getCurrentTest();
+            saveGoodTest(t);
+        }
+        if (mappingID == RANDOMISE_TARGET_ID){ // bleyeueurrrr
+            targetSynth.randomiseParams();
+            return;
+        }
+        if (mappingID == TRIGGER_TARGET_ID){
+            playTargetButtonPressed();
+            
+        }
+        if (mappingID == TRIGGER_CANDIDATE_ID){
+            // log event
+            sendSynthValuesAgain();
+            candidateSynth.trigger();
+            eventLogger.logEvent(CANDIDATE_PLAYED);
+            // flash panel?
+            panel->flash();
+            return;
+        }
+        if (mappingID == SUBMIT_CANDIDATE){
+            // log event
+            submitPressed();
+            
+            return;
+        }
+        if (mappingID == CRAP_TEST_ID){
+            // this is rubbish! send a log of target values, and mapping ids
+            vector<int> data;
+            vector<int> tvals = targetSynth.getAllParamValues();
+            vector<int> pidx = testController->getCurrentChangeableParams();
+            data.insert(data.end(), tvals.begin(), tvals.end());
+            data.insert(data.end(), pidx.begin(), pidx.end());
+
+            eventLogger.logEvent(CRAP_TEST, data);
+        }
+        if(mappingID == SHOW_HIDE_PANEL){
+            static bool showing;
+            
+            if(showing){
+                cout << " showing"<<endl;
+                
+                panel->show();
+                
+            }else{
+                cout << " hiding"<<endl;
+                panel->hide();
+            }
+            showing = !showing;
+        }
+        if(mappingID == SHOW_HIDE_HINT){
+            static bool showingHint;
+            if(showingHint){
+                panel->showHint(false);
+                showingHint = false;
+            }else{
+                panel->showHint(true);
+                showingHint = true;
+            }
+        }
+    }
+    // called from UI
+    void paramChangeCallback(int mappingID, int value){
+        candidateSynth.paramChangeCallback(mappingID, value);
+        vector<int> evtData;
+        evtData.push_back(mappingID); // or just index?
+        evtData.push_back(value);
+        
+        eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
+    };
+
+    // could template for ui element type??
+    void mapButtonToAction(UIElement* control, int mappingID){
+        UICallbackFunction callbackF;
+        callbackF = boost::bind(&MessageOrganiser::buttonPressCallback, this, _1,_2);
+        control->addHandler(callbackF, mappingID);
+        currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
+    }
+
+    
+    void midiFromLeap(int ctl_num, int ctl_val){
+        
+  
+        if (!okToGetLeapMidi){
+            return;
+        }
+        
+        // this fails - try pointer version?
+
+        Test *theTest = testController->getCurrentTestPtr();
+        if (theTest == NULL) return;
+        
+        box3D->setValueAndScale(ctl_num, ctl_val);
+
+        
+        vector<int> ci = theTest->getChangeableIndices();
+        vector<int> mids = candidateSynth.getMappingIDForIndices(ci);
+        if (ctl_num >= mids.size() || ctl_num < 0) return;
+        
+        candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val);
+        
+        vector<int> evtData;
+        evtData.push_back(mids[ctl_num]); // or just index?
+        evtData.push_back(ctl_val);
+        
+        eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
+        // also call UI object
+        // get mapping ID for
+        // setUIToParam(ctl_num, ctl_val);
+    }
+
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PDSynthWrapper.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,229 @@
+//
+//  pdSynthWrapper.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 14/01/2014.
+//
+//
+
+#pragma once
+
+#include "AppCore.h"
+#include "eventLogger.h"
+#include "ofxPd.h"
+#include <string>
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+#include "SynthParam.h"
+
+
+//---------------------------------------------------------------------
+//---------------------------------------------------------------------
+//---------------------------------------------------------------------
+
+class PDSynthWrapper {
+public:
+    void init(AppCore* aCore, string sp){
+        core = aCore;
+        
+        synthPrefix = sp;
+        // init all the params, refer to synth in pd patch
+        timbreParams.push_back(SynthParam(64,aCore,"Pitch",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"Pulse",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"Attack",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"Decay",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"FiltTyp",sp));
+        timbreParams.push_back(SynthParam(64,aCore,"FiltFrq",sp));
+        //timbreParams.push_back(SynthParam(64,aCore,"reson",sp));
+        
+        if (timbreParams.size() != TOTAL_NUM_PARAMS){
+            cout << "ERROR ERROR: WRONG NUM OF timbreParams or TOTAL_NUM_PARAMS" << endl;
+        }
+        cout << "initialised synth: " << sp << " with " << timbreParams.size() << " params" << endl;
+    };
+    void sendAllParams(){
+        std::vector<SynthParam>::const_iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            psp->sendToPD();
+        }
+    }
+    void sendVolume(int value){
+        List toPD;
+        toPD.addSymbol(synthPrefix);
+        toPD.addSymbol("Volume");
+        toPD.addFloat(value); // rounding here??
+        
+        core->pd.sendList("fromOF", toPD);
+    }
+    void setNoteLength(int lms){
+        List toPD;
+        toPD.addSymbol(synthPrefix);
+        toPD.addSymbol("noteLength");
+        toPD.addFloat(lms); // volume here, just in case??
+        
+        core->pd.sendList("fromOF", toPD);
+    }
+    const int getParamValueForID(int pid){
+        int v = 0;
+        std::vector<SynthParam>::const_iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            if (psp->getID() == pid){
+                v = psp->getValue();
+                return v;
+            }
+            
+        }
+        cout << "ERROR ERROR getParamValueForID not found" << endl;
+    }
+    const int getMappingIDForName(string name) const{
+        
+        int rID = -1;
+        std::vector<SynthParam>::const_iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            if (psp->getName() == name){
+                rID = psp->getID();
+                return rID;
+            }
+            
+        }
+        cout << "ERROR ERROR getMappingIDForName not found" << endl;
+    };
+    const string getNameForMappingID(int pid) const{
+        
+        string rname = "no name";
+        std::vector<SynthParam>::const_iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            if (psp->getID() == pid){
+                rname = psp->getName();
+                return rname;
+            }
+            
+        }
+        cout << "ERROR ERROR getNameForMappingID not found" << endl;
+    };
+    vector<int> getMappingIDForIndices(vector<int> idx){
+        vector<int> result;
+        
+        for(int i = 0 ; i < idx.size(); i++){
+            if (idx[i] < timbreParams.size()){
+                int mapid = timbreParams[idx[i]].getID();
+                
+                result.push_back(mapid);
+                //cout << " Map id for param no: " << idx[i] << " is  " << *(result.end()-1);
+            }else{
+                cout << "ERROR ERROR: index bigger than num timbre params" << endl;
+                
+            }
+        }
+        return result;
+    }
+    
+    void paramChangeCallback(int mappingID, int value){
+
+        // look for id in params
+        std::vector<SynthParam>::iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            if ( psp->getID() == mappingID){
+                psp->setValue(value);
+                return;
+            }
+        }
+        cout << "ERROR ERROR: paramChangeCallback mappingID not found" << endl;
+    };
+    
+    void trigger(){
+        // play the noise
+        List toPD;
+        toPD.addSymbol(synthPrefix);
+        toPD.addSymbol("playSound");
+        toPD.addFloat(1.0); // volume here, just in case??
+        
+        core->pd.sendList("fromOF", toPD);
+
+    };
+    
+    void randomiseParams(){
+        
+        cout << " randomising" << endl;
+        std::vector<SynthParam>::iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+
+            int value = ofRandom(0,127);
+            psp->setValue(value);
+
+        }
+        
+    };
+
+    void setSameAsOtherSynth(const PDSynthWrapper* otherSynth){
+        // loop thru all params and set them to other synth
+        std::vector<SynthParam>::iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            psp->setValue(otherSynth->getParamValueFromName(psp->getName()));
+    
+        }
+    };
+    
+    vector<int> randomiseParamSubset(int howMany){
+        vector<int> randomisedIDs;
+        for (int i=0;i<howMany;i++){
+            
+            int value = ofRandom(0,127);
+            timbreParams[i].setValue(value);
+            randomisedIDs.push_back(i);
+            
+        }
+        return randomisedIDs;
+        
+    };
+    
+    const int getParamValueFromName(string name) const{
+        
+        int value = -1;
+        std::vector<SynthParam>::const_iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            if (psp->getName() == name){
+                value = psp->getValue();
+                return value;
+            }
+            
+        }
+        cout << "ERROR ERROR: getParamValueFromName name not found" << endl;
+    };
+    
+    const int getNumParams(){
+        return timbreParams.size();
+    };
+    
+    void setAllParams(vector<int> params){
+        if(params.size() != timbreParams.size()){
+            cout << "Error not right number of params in set in synth" << endl;
+            return;
+        }
+        std::vector<SynthParam>::iterator psp;
+        int i=0;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            psp->setValue(params[i]);
+            i++;
+        }
+        
+
+    }
+    vector<int> getAllParamValues(){
+        vector<int> pl;
+        std::vector<SynthParam>::const_iterator psp;
+        for(psp = timbreParams.begin(); psp < timbreParams.end(); psp++){
+            pl.push_back(psp->getValue());
+        }
+        return pl;
+    }
+private:
+    string synthPrefix;
+    AppCore* core;
+    
+    vector<SynthParam> timbreParams; // array of everything in synth
+  
+};
+
+//---------------------------------------------------------------------
+//---------------------------------------------------------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Question.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,25 @@
+//
+//  Question.h
+//  sonicZoom
+//
+//  Created by Robert Tubb on 21/01/2013.
+//
+// included by Qviewcont
+#define NUM_CHOICES 5
+
+#import <Foundation/Foundation.h>
+typedef enum QuestionType{AGREE_DISAGREE, SLIDERS_ZOOMER} QuestionType;
+
+@interface Question : NSObject
+{
+  
+    
+}
+@property (strong, nonatomic) NSString *questionText;
+@property QuestionType questionType;
+@property int answer; // answer 0 means no answer was given (the blank line in picker) this distiguishes between "neither" and "don't know / no answer"
+
+-(id)initWithTextAndType:(NSString *)text:(QuestionType)type;
++ (int)count;
++(NSArray *)answersWithType:(QuestionType)type;
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Question.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,65 @@
+//
+//  Question.m
+//  sonicZoom
+//
+//  Created by Robert Tubb on 21/01/2013.
+//
+//
+
+#import "Question.h"
+
+@implementation Question
+
+@synthesize questionText = _questionText;
+@synthesize questionType = _questionType;
+@synthesize answer = _answer; 
+
+static int theCount = 0;
+// WRONG
+-(id)initWithTextAndType:(NSString *)text:(QuestionType)type{
+    self = [super init];
+    if(self){
+        self.questionText = text;
+        self.questionType = type;
+        self.answer = -1;
+    }
+    
+    return self;
+    
+}
+////
+- (id)init  
+{
+    return [self initWithTextAndType:@"Quo Vadis?":AGREE_DISAGREE];
+}
+
++ (int) count { return theCount; }
++ (void) setCount:(int)c { theCount = c; }
+
+
+
++(NSArray *)answersWithType:(QuestionType)type{
+// get the set of answers depending on what type the q was
+    // pseudo static variable
+    if(type == AGREE_DISAGREE){
+        [Question setCount:NUM_CHOICES];
+        
+        NSArray *answers =  [[[NSArray alloc] initWithObjects:
+                     @"Strongly agree",@"Agree", @"Neither agree nor disagree",
+                     @"Disagree",@"Strongly disagree", nil] autorelease];
+
+        return answers;
+        
+    }else if(type == SLIDERS_ZOOMER){
+        [Question setCount:NUM_CHOICES];
+        NSArray *answers =   [[[NSArray alloc] initWithObjects:
+                 @"definitely the Sliders", @"maybe the Sliders", @"Neither/Both equal",
+                @"maybe the Zoomer", @"definitely the Zoomer", nil] autorelease];
+
+        return answers;
+    }else{
+        return nil;
+    }
+}
+///
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QuestionnaireViewController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,52 @@
+//
+//  QuestionnaireViewController.h
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 16/01/2013.
+//
+//
+
+#import <UIKit/UIKit.h>
+
+#import "Question.h"
+
+@interface QuestionnaireViewController : UIViewController
+<UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate>
+{
+
+    UIPickerView       *picker;
+
+    
+}
+@property (retain, nonatomic) IBOutlet UILabel *questionText;
+@property (retain, nonatomic) IBOutlet UILabel *titleText;
+@property (retain, nonatomic) IBOutlet UIButton *finishButton;
+@property (retain, nonatomic) IBOutlet UIButton *nextButton;
+@property (retain, nonatomic) IBOutlet UIButton *previousButton;
+
+@property (strong, nonatomic) IBOutlet UIPickerView *picker;
+
+@property (retain, nonatomic) IBOutlet UITextView *commentText;
+@property (retain, nonatomic) IBOutlet UISegmentedControl *numberChooser;
+@property (retain, nonatomic) IBOutlet UIView *interfacePreferenceOptions;
+@property (retain, nonatomic) IBOutlet UIView *lickertOptions;
+@property (retain, nonatomic) IBOutlet UILabel *pleaseAnswer;
+
+//----------------------------------------------------------------
+- (IBAction)answerChosen:(id)sender;
+
+-(IBAction)hide:(id)sender;
+-(IBAction)show:(id)sender;
+- (IBAction)nextQuestionPressed:(id)sender;
+- (IBAction)previousQuestionPressed:(id)sender;
+-(void)unlockAll;
+//----------------------------------------------------------------
+- (void)setAppRef:(id)theOFApp;
+- (void)populateQuestionArray;
+- (void)loadQuestion:(NSInteger)questionIndex;
+//----------------------------------------------------------------
+@end
+
+//----------------------------------------------------------------
+//----------------------------------------------------------------
+//----------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QuestionnaireViewController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,306 @@
+//
+//  QuestionnaireViewController.m
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 16/01/2013.
+//
+//
+
+#import "QuestionnaireViewController.h"
+
+#include "testApp.h"
+
+#pragma mark -
+#pragma mark QuestionnaireViewController
+
+@interface QuestionnaireViewController ()
+    // the "model" is an array of questions 
+@property (strong, nonatomic)       NSArray * questionArray;
+@property (nonatomic)               NSInteger currentQuestionIndex;
+@property (nonatomic, assign)       id theOFAppRef;
+
+/*
+
+
+*/
+
+@end
+
+@implementation QuestionnaireViewController
+
+@synthesize picker;
+@synthesize nextButton = _nextButton;
+@synthesize questionArray = _questionArray;
+
+
+//----------------------------------------------------------------
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        // Custom initialization
+        
+        [self populateQuestionArray ];
+        
+    }
+    return self;
+}
+- (void)setAppRef:(id)theOFApp{
+    self.theOFAppRef = theOFApp;
+    
+}
+//----------------------------------------------------------------
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    // Do any additional setup after loading the view from its nib.
+    self.currentQuestionIndex = 0;
+    
+    // load question 1    
+    [self loadQuestion:self.currentQuestionIndex];
+    
+    self.previousButton.hidden = NO; //  bother
+    self.commentText.hidden = YES;
+    self.finishButton.hidden = YES;
+    self.nextButton.hidden = YES;
+    
+    self.lickertOptions.hidden = NO;
+    self.interfacePreferenceOptions.hidden = YES;
+}
+//----------------------------------------------------------------
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];
+    // Dispose of any resources that can be recreated.
+}
+//----------------------------------------------------------------
+- (void)dealloc {
+
+    [super dealloc];
+}
+//----------------------------------------------------------------
+- (void)viewDidUnload {
+    [self.questionArray release];
+    [self setQuestionText:nil];
+    [self setTitleText:nil];
+    [self setFinishButton:nil];
+    [self setNextButton:nil];
+    [self setPreviousButton:nil];
+    [self setCommentText:nil];
+    [self setNumberChooser:nil];
+    [self setInterfacePreferenceOptions:nil];
+    [self setLickertOptions:nil];
+    [self setPleaseAnswer:nil];
+    [super viewDidUnload];
+}
+//----------------------------------------------------------------
+-(IBAction)hide:(id)sender{
+    // called when finish button hit
+    // c++ call with NSArray argument??
+    // load answers into a c++ vector;
+    vector<int> answersArray;
+
+    Question *q;
+    
+    for(int i=0;i<[self.questionArray count];i++){
+        q = [self.questionArray objectAtIndex:i];
+        answersArray.push_back(q.answer);
+        
+    }
+    const char *userComments = [self.commentText.text cStringUsingEncoding: NSUTF8StringEncoding];
+    [self.commentText resignFirstResponder];
+    
+	self.view.hidden = YES;
+    ((testApp *)self.theOFAppRef)->questionnaireHidden(answersArray, userComments);
+    
+}
+
+//----------------------------------------------------------------
+-(IBAction)show:(id)sender{
+	self.view.hidden = NO;
+}
+//----------------------------------------------------------------
+
+- (IBAction)nextQuestionPressed:(id)sender {
+    // save answer ? no button did that hopefully
+    
+    // if last question show thanks
+    // else go to next
+    self.currentQuestionIndex++;
+    if(self.currentQuestionIndex >= [self.questionArray count]){
+        [self showThanks];
+    }else{
+        [self loadQuestion:self.currentQuestionIndex];
+
+    }
+}
+//----------------------------------------------------------------
+- (IBAction)previousQuestionPressed:(id)sender {
+    self.currentQuestionIndex--;
+    if(self.currentQuestionIndex < 0){
+        // nothing
+        self.currentQuestionIndex = 0;
+    }else{
+        [self loadQuestion:self.currentQuestionIndex];
+    }
+}
+
+//----------------------------------------------------------------
+
+- (void)showThanks{
+    // hide next question button
+    self.nextButton.hidden = YES;
+    // hide selector
+    self.picker.hidden = YES;
+    self.previousButton.hidden = YES;
+    self.finishButton.hidden = NO;
+    
+    self.lickertOptions.hidden = YES;
+    self.interfacePreferenceOptions.hidden = YES;
+    
+    self.titleText.text = @"Thank you!";
+    self.numberChooser.hidden = YES;
+    self.commentText.hidden = NO;
+    
+    self.questionText.text = @"Thanks for helping science help you. Feel free to add further comments in the text box below, and then press 'finish' to go back and use the app.";
+}
+
+//----------------------------------------------------------------
+- (void)loadQuestion:(NSInteger)questionIndex {
+    // populate text fields with question
+    NSString *qtitle;
+    qtitle = [@"Question " stringByAppendingFormat:@"%d / %d",questionIndex+1, [self.questionArray count]];
+    self.titleText.text = qtitle;
+    
+    Question *curQ = [self.questionArray objectAtIndex:self.currentQuestionIndex];
+    
+    self.questionText.text = curQ.questionText;
+    
+    
+    // refresh picker view content
+    //[picker reloadComponent:0];
+
+    // show correct option number labels
+    if(curQ.questionType == AGREE_DISAGREE){
+        self.lickertOptions.hidden = NO;
+        self.interfacePreferenceOptions.hidden = YES;
+    }else if(curQ.questionType == SLIDERS_ZOOMER){
+        self.lickertOptions.hidden = YES;
+        self.interfacePreferenceOptions.hidden = NO;
+    }
+
+    //NSLog(@"Prev answer answerInt %d", curQ.answer);
+    //[picker selectRow:2 inComponent:0 animated:YES];
+    
+    // what about unselecting segment?
+
+}
+// 1/3/13 removed q 6 and 15. now only 15 qs
+//----------------------------------------------------------------
+- (void)populateQuestionArray{
+// potential leak
+    self.questionArray = [NSArray arrayWithObjects:
+                          [[Question alloc] initWithTextAndType:@"I am familiar with music software and sound synthesis.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"The ability to retrace my steps using the history path was useful...":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"The best interface for discovering interesting sounds quickly was...":SLIDERS_ZOOMER],
+                          [[Question alloc] initWithTextAndType:@"The best interface for fine tuning a sound was...":SLIDERS_ZOOMER],
+                          [[Question alloc] initWithTextAndType:@"The correspondence between the sliders and the grid was understandable.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"Scrolling a greater distance on the grid seemed to correspond to larger difference in the sound.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"The interface that I felt more in control using was...":SLIDERS_ZOOMER],
+                          [[Question alloc] initWithTextAndType:@"Being able to see previously saved presets on the grid is useful.":AGREE_DISAGREE],  //
+                          [[Question alloc] initWithTextAndType:@"The interface that felt more creative was...":SLIDERS_ZOOMER],
+                          [[Question alloc] initWithTextAndType:@"The range of sounds was too limited to be able to judge the eventual usefulness of the interface.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"The interface better for generating new ideas was...":SLIDERS_ZOOMER], 
+                          [[Question alloc] initWithTextAndType:@"The interface better for performing live would be...":SLIDERS_ZOOMER],
+                          [[Question alloc] initWithTextAndType:@"The Zoomer was an improvement on just using a randomiser.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"The combination of Zoomer and Sliders was better than either individually.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"I enjoy 'happy accidents' in the creative process.":AGREE_DISAGREE],
+                          [[Question alloc] initWithTextAndType:@"Overall, the interface I preferred using was...":SLIDERS_ZOOMER], // ??????
+                          nil];
+ // The zoomer seemed more appropriate to explore the synth sound controls (red) than the note sequence controls (blue)
+// I enjoyed the sounds produced
+
+}
+
+//----------------------------------------------------------------
+#pragma mark -
+#pragma mark PickerView DataSource
+
+- (NSInteger)numberOfComponentsInPickerView:
+(UIPickerView *)pickerView
+{
+    return 1;
+}
+//----------------------------------------------------------------
+- (NSInteger)pickerView:(UIPickerView *)pickerView
+numberOfRowsInComponent:(NSInteger)component
+{
+
+    return NUM_CHOICES; // always 6
+}
+//----------------------------------------------------------------
+- (NSString *)pickerView:(UIPickerView *)pickerView
+             titleForRow:(NSInteger)row
+            forComponent:(NSInteger)component
+{
+    Question *curQ = [self.questionArray objectAtIndex:self.currentQuestionIndex];
+
+    // get array of answers from Question class
+    NSArray * answers = [Question answersWithType:curQ.questionType];
+    return [answers objectAtIndex:row];
+
+}
+//----------------------------------------------------------------
+#pragma mark -
+#pragma mark PickerView Delegate
+-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
+      inComponent:(NSInteger)component
+{
+    Question *curQ = [self.questionArray objectAtIndex:self.currentQuestionIndex];
+    // set question answerArray
+    curQ.answer = row;
+    
+    // chek wot we just rote
+    
+    NSLog(@"Answer: %d",curQ.answer);
+
+}
+//----------------------------------------------------------------
+#pragma mark UITextViewDelegate functions
+/*
+ This answer was useful to me, but I was also looking for the callback function from the "Go" button, which I found is:
+ - (BOOL) textFieldShouldReturn:(UITextField *)textField { // Customer code return YES; }
+ 
+ You will need to send the UITextField delegate to your view controller for that to work.
+ 
+ */
+ - (BOOL) textFieldShouldReturn:(UITextField *)textField {
+     // Customer code
+     NSLog(@"RETURN DELEGATE");
+     [self hide:self ];
+     return NO;
+ }
+- (IBAction)answerChosen:(id)sender {
+    self.pleaseAnswer.hidden = YES;
+    UISegmentedControl *seg = (UISegmentedControl *)sender;
+    Question *curQ = [self.questionArray objectAtIndex:self.currentQuestionIndex];
+    // set question answerArray
+    curQ.answer = seg.selectedSegmentIndex;
+    
+    // chek wot we just rote
+    
+    NSLog(@"Answer: %d",curQ.answer);
+    
+    // automatically go next q
+    self.currentQuestionIndex++;
+    if(self.currentQuestionIndex >= [self.questionArray count]){
+        [self showThanks];
+    }else{
+        [self loadQuestion:self.currentQuestionIndex];
+        
+    }
+    
+}
+@end // end implementation
+//----------------------------------------------------------------
+//----------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QuestionnaireViewController.xib	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,1117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
+	<data>
+		<int key="IBDocument.SystemTarget">1280</int>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			<string key="NS.object.0">2083</string>
+		</object>
+		<array key="IBDocument.IntegratedClassDependencies">
+			<string>IBProxyObject</string>
+			<string>IBUIButton</string>
+			<string>IBUILabel</string>
+			<string>IBUIPickerView</string>
+			<string>IBUISegmentedControl</string>
+			<string>IBUITextView</string>
+			<string>IBUIView</string>
+		</array>
+		<array key="IBDocument.PluginDependencies">
+			<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+		</array>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<object class="IBProxyObject" id="841351856">
+				<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+			<object class="IBProxyObject" id="606714003">
+				<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+			<object class="IBUIView" id="766721923">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">292</int>
+				<array class="NSMutableArray" key="NSSubviews">
+					<object class="IBUIButton" id="871929113">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{324, 706}, {121, 44}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="960474577"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<int key="IBUIContentHorizontalAlignment">0</int>
+						<int key="IBUIContentVerticalAlignment">0</int>
+						<int key="IBUIButtonType">1</int>
+						<string key="IBUINormalTitle">Finish</string>
+						<object class="NSColor" key="IBUIHighlightedTitleColor" id="1041582678">
+							<int key="NSColorSpace">3</int>
+							<bytes key="NSWhite">MQA</bytes>
+						</object>
+						<object class="NSColor" key="IBUINormalTitleColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
+						</object>
+						<object class="NSColor" key="IBUINormalTitleShadowColor" id="907174598">
+							<int key="NSColorSpace">3</int>
+							<bytes key="NSWhite">MC41AA</bytes>
+						</object>
+						<object class="IBUIFontDescription" key="IBUIFontDescription" id="113804367">
+							<int key="type">2</int>
+							<double key="pointSize">15</double>
+						</object>
+						<object class="NSFont" key="IBUIFont" id="774363385">
+							<string key="NSName">Helvetica-Bold</string>
+							<double key="NSSize">15</double>
+							<int key="NSfFlags">16</int>
+						</object>
+					</object>
+					<object class="IBUILabel" id="783180915">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{143, 220}, {275, 53}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="692955189"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<bool key="IBUIClipsSubviews">YES</bool>
+						<int key="IBUIContentMode">7</int>
+						<bool key="IBUIUserInteractionEnabled">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<string key="IBUIText">Question 1</string>
+						<object class="NSColor" key="IBUITextColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MCAwLjg3MTEwNjY5ODMgMQA</bytes>
+						</object>
+						<nil key="IBUIHighlightedColor"/>
+						<int key="IBUIBaselineAdjustment">0</int>
+						<object class="IBUIFontDescription" key="IBUIFontDescription">
+							<string key="name">Helvetica</string>
+							<string key="family">Helvetica</string>
+							<int key="traits">0</int>
+							<double key="pointSize">31</double>
+						</object>
+						<object class="NSFont" key="IBUIFont">
+							<string key="NSName">Helvetica</string>
+							<double key="NSSize">31</double>
+							<int key="NSfFlags">16</int>
+						</object>
+						<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+					</object>
+					<object class="IBUILabel" id="838658605">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{144, 281}, {472, 138}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="660724550"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<bool key="IBUIClipsSubviews">YES</bool>
+						<int key="IBUIContentMode">7</int>
+						<bool key="IBUIUserInteractionEnabled">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<string key="IBUIText">Questions:</string>
+						<object class="NSColor" key="IBUITextColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC45Mjc2NzQyNjcgMC45MjIwNTE5OTg4IDAuOTMzMjk2NTM1MwA</bytes>
+						</object>
+						<nil key="IBUIHighlightedColor"/>
+						<int key="IBUIBaselineAdjustment">0</int>
+						<int key="IBUINumberOfLines">4</int>
+						<object class="IBUIFontDescription" key="IBUIFontDescription">
+							<int key="type">1</int>
+							<double key="pointSize">22</double>
+						</object>
+						<object class="NSFont" key="IBUIFont">
+							<string key="NSName">Helvetica</string>
+							<double key="NSSize">22</double>
+							<int key="NSfFlags">16</int>
+						</object>
+						<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+						<double key="preferredMaxLayoutWidth">472</double>
+					</object>
+					<object class="IBUIButton" id="960474577">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{425, 706}, {121, 44}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="791686696"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<int key="IBUIContentHorizontalAlignment">0</int>
+						<int key="IBUIContentVerticalAlignment">0</int>
+						<int key="IBUIButtonType">1</int>
+						<string key="IBUINormalTitle">Next Question</string>
+						<reference key="IBUIHighlightedTitleColor" ref="1041582678"/>
+						<object class="NSColor" key="IBUINormalTitleColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
+						</object>
+						<reference key="IBUINormalTitleShadowColor" ref="907174598"/>
+						<reference key="IBUIFontDescription" ref="113804367"/>
+						<reference key="IBUIFont" ref="774363385"/>
+					</object>
+					<object class="IBUIButton" id="356964106">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{51, 706}, {157, 44}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="871929113"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<int key="IBUIContentHorizontalAlignment">0</int>
+						<int key="IBUIContentVerticalAlignment">0</int>
+						<int key="IBUIButtonType">1</int>
+						<string key="IBUINormalTitle">Previous Question</string>
+						<reference key="IBUIHighlightedTitleColor" ref="1041582678"/>
+						<object class="NSColor" key="IBUINormalTitleColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
+						</object>
+						<reference key="IBUINormalTitleShadowColor" ref="907174598"/>
+						<reference key="IBUIFontDescription" ref="113804367"/>
+						<reference key="IBUIFont" ref="774363385"/>
+					</object>
+					<object class="IBUIPickerView" id="791686696">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">-2147483358</int>
+						<string key="NSFrame">{{413, 788}, {590, 216}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<bool key="IBUIShowsSelectionIndicator">YES</bool>
+					</object>
+					<object class="IBUITextView" id="960632081">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{212, 468}, {334, 230}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="356964106"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<object class="NSColor" key="IBUIBackgroundColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MSAxIDEAA</bytes>
+						</object>
+						<bool key="IBUIClipsSubviews">YES</bool>
+						<bool key="IBUIMultipleTouchEnabled">YES</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<bool key="IBUIShowsHorizontalScrollIndicator">NO</bool>
+						<string key="IBUIText"/>
+						<object class="IBUITextInputTraits" key="IBUITextInputTraits">
+							<int key="IBUIAutocapitalizationType">2</int>
+							<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+						</object>
+						<object class="IBUIFontDescription" key="IBUIFontDescription">
+							<int key="type">1</int>
+							<double key="pointSize">14</double>
+						</object>
+						<object class="NSFont" key="IBUIFont">
+							<string key="NSName">Helvetica</string>
+							<double key="NSSize">14</double>
+							<int key="NSfFlags">16</int>
+						</object>
+					</object>
+					<object class="IBUISegmentedControl" id="660724550">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{51, 533}, {667, 44}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="960632081"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<int key="IBNumberOfSegments">5</int>
+						<array key="IBSegmentTitles">
+							<string>1</string>
+							<string>2</string>
+							<string>3</string>
+							<string>4</string>
+							<string>5</string>
+						</array>
+						<array class="NSMutableArray" key="IBSegmentWidths">
+							<real value="0.0"/>
+							<real value="0.0"/>
+							<real value="0.0"/>
+							<real value="0.0"/>
+							<real value="0.0"/>
+						</array>
+						<array class="NSMutableArray" key="IBSegmentEnabledStates">
+							<boolean value="YES"/>
+							<boolean value="YES"/>
+							<boolean value="YES"/>
+							<boolean value="YES"/>
+							<boolean value="YES"/>
+						</array>
+						<array class="NSMutableArray" key="IBSegmentContentOffsets">
+							<string>{0, 0}</string>
+							<string>{0, 0}</string>
+							<string>{0, 0}</string>
+							<string>{0, 0}</string>
+							<string>{0, 0}</string>
+						</array>
+						<array class="NSMutableArray" key="IBSegmentImages">
+							<object class="NSNull" id="4"/>
+							<reference ref="4"/>
+							<reference ref="4"/>
+							<reference ref="4"/>
+							<reference ref="4"/>
+						</array>
+						<bool key="IBMomentary">YES</bool>
+					</object>
+					<object class="IBUIView" id="638395666">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">-2147483356</int>
+						<array class="NSMutableArray" key="NSSubviews">
+							<object class="IBUILabel" id="316486170">
+								<reference key="NSNextResponder" ref="638395666"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{7, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="638395666"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="340544853"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Definitely the sliders</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<object class="NSColorSpace" key="NSCustomColorSpace" id="765822392">
+										<int key="NSID">1</int>
+									</object>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<object class="IBUIFontDescription" key="IBUIFontDescription" id="973990875">
+									<int key="type">1</int>
+									<double key="pointSize">17</double>
+								</object>
+								<object class="NSFont" key="IBUIFont" id="471794535">
+									<string key="NSName">Helvetica</string>
+									<double key="NSSize">17</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="340544853">
+								<reference key="NSNextResponder" ref="638395666"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{139, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="638395666"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="674807401"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Maybe the sliders</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="674807401">
+								<reference key="NSNextResponder" ref="638395666"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{267, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="638395666"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="85392105"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Neither / both equal</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="85392105">
+								<reference key="NSNextResponder" ref="638395666"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{399, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="638395666"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="36668958"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Maybe the Zoomer</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="36668958">
+								<reference key="NSNextResponder" ref="638395666"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{535, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="638395666"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="838658605"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Definitely the Zoomer</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+						</array>
+						<string key="NSFrame">{{51, 416}, {667, 118}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="316486170"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<object class="NSColor" key="IBUIBackgroundColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC4yNzY0OTQ1NjUyIDAuMjc2NDk0NTY1MiAwLjI3NjQ5NDU2NTIAA</bytes>
+						</object>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+					</object>
+					<object class="IBUIView" id="692955189">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">-2147483356</int>
+						<array class="NSMutableArray" key="NSSubviews">
+							<object class="IBUILabel" id="353586444">
+								<reference key="NSNextResponder" ref="692955189"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{7, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="692955189"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="790263268"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Strongly disagree</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="790263268">
+								<reference key="NSNextResponder" ref="692955189"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{139, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="692955189"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="355647270"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Disagree</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="355647270">
+								<reference key="NSNextResponder" ref="692955189"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{267, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="692955189"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="404206660"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Neither agree nor disagree</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="404206660">
+								<reference key="NSNextResponder" ref="692955189"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{399, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="692955189"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="78723594"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Agree</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+							<object class="IBUILabel" id="78723594">
+								<reference key="NSNextResponder" ref="692955189"/>
+								<int key="NSvFlags">292</int>
+								<string key="NSFrame">{{535, 29}, {132, 69}}</string>
+								<reference key="NSSuperview" ref="692955189"/>
+								<reference key="NSWindow"/>
+								<reference key="NSNextKeyView" ref="638395666"/>
+								<string key="NSReuseIdentifierKey">_NS:9</string>
+								<bool key="IBUIOpaque">NO</bool>
+								<bool key="IBUIClipsSubviews">YES</bool>
+								<int key="IBUIContentMode">7</int>
+								<bool key="IBUIUserInteractionEnabled">NO</bool>
+								<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+								<string key="IBUIText">Strongly agree</string>
+								<object class="NSColor" key="IBUITextColor">
+									<int key="NSColorSpace">1</int>
+									<bytes key="NSRGB">MSAxIDEAA</bytes>
+									<reference key="NSCustomColorSpace" ref="765822392"/>
+								</object>
+								<nil key="IBUIHighlightedColor"/>
+								<int key="IBUIBaselineAdjustment">0</int>
+								<int key="IBUINumberOfLines">2</int>
+								<int key="IBUITextAlignment">1</int>
+								<reference key="IBUIFontDescription" ref="973990875"/>
+								<reference key="IBUIFont" ref="471794535"/>
+								<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+								<double key="preferredMaxLayoutWidth">132</double>
+							</object>
+						</array>
+						<string key="NSFrame">{{50, 416}, {667, 118}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="353586444"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<object class="NSColor" key="IBUIBackgroundColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MC4yNzY0OTQ1NjUyIDAuMjc2NDk0NTY1MiAwLjI3NjQ5NDU2NTIAA</bytes>
+						</object>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+					</object>
+					<object class="IBUILabel" id="831894070">
+						<reference key="NSNextResponder" ref="766721923"/>
+						<int key="NSvFlags">292</int>
+						<string key="NSFrame">{{143, 104}, {434, 21}}</string>
+						<reference key="NSSuperview" ref="766721923"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="783180915"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="IBUIOpaque">NO</bool>
+						<bool key="IBUIClipsSubviews">YES</bool>
+						<int key="IBUIContentMode">7</int>
+						<bool key="IBUIUserInteractionEnabled">NO</bool>
+						<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+						<string key="IBUIText">Thanks very much. Now please answer a few questions...</string>
+						<object class="NSColor" key="IBUITextColor">
+							<int key="NSColorSpace">1</int>
+							<bytes key="NSRGB">MSAxIDEAA</bytes>
+							<reference key="NSCustomColorSpace" ref="765822392"/>
+						</object>
+						<nil key="IBUIHighlightedColor"/>
+						<int key="IBUIBaselineAdjustment">0</int>
+						<reference key="IBUIFontDescription" ref="973990875"/>
+						<reference key="IBUIFont" ref="471794535"/>
+						<bool key="IBUIAdjustsFontSizeToFit">NO</bool>
+					</object>
+				</array>
+				<string key="NSFrameSize">{1024, 768}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSWindow"/>
+				<reference key="NSNextKeyView" ref="831894070"/>
+				<object class="NSColor" key="IBUIBackgroundColor">
+					<int key="NSColorSpace">1</int>
+					<bytes key="NSRGB">MCAwIDAAA</bytes>
+				</object>
+				<bool key="IBUIOpaque">NO</bool>
+				<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+				<object class="IBUISimulatedOrientationMetrics" key="IBUISimulatedOrientationMetrics">
+					<int key="IBUIInterfaceOrientation">3</int>
+					<int key="interfaceOrientation">3</int>
+				</object>
+				<object class="IBUIScreenMetrics" key="IBUISimulatedDestinationMetrics">
+					<string key="IBUISimulatedSizeMetricsClass">IBUIScreenMetrics</string>
+					<object class="NSMutableDictionary" key="IBUINormalizedOrientationToSizeMap">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<array key="dict.sortedKeys">
+							<integer value="1"/>
+							<integer value="3"/>
+						</array>
+						<array key="dict.values">
+							<string>{768, 1024}</string>
+							<string>{1024, 768}</string>
+						</array>
+					</object>
+					<string key="IBUITargetRuntime">IBIPadFramework</string>
+					<string key="IBUIDisplayName">iPad Full Screen</string>
+					<int key="IBUIType">1</int>
+				</object>
+				<string key="targetRuntimeIdentifier">IBIPadFramework</string>
+			</object>
+		</array>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<array class="NSMutableArray" key="connectionRecords">
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="766721923"/>
+					</object>
+					<int key="connectionID">3</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">questionText</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="838658605"/>
+					</object>
+					<int key="connectionID">41</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">titleText</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="783180915"/>
+					</object>
+					<int key="connectionID">42</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">finishButton</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="871929113"/>
+					</object>
+					<int key="connectionID">51</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">nextButton</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="960474577"/>
+					</object>
+					<int key="connectionID">52</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">picker</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="791686696"/>
+					</object>
+					<int key="connectionID">59</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">previousButton</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="356964106"/>
+					</object>
+					<int key="connectionID">60</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">commentText</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="960632081"/>
+					</object>
+					<int key="connectionID">64</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">numberChooser</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="660724550"/>
+					</object>
+					<int key="connectionID">72</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">interfacePreferenceOptions</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="638395666"/>
+					</object>
+					<int key="connectionID">81</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">lickertOptions</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="692955189"/>
+					</object>
+					<int key="connectionID">88</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">pleaseAnswer</string>
+						<reference key="source" ref="841351856"/>
+						<reference key="destination" ref="831894070"/>
+					</object>
+					<int key="connectionID">91</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">nextQuestionPressed:</string>
+						<reference key="source" ref="960474577"/>
+						<reference key="destination" ref="841351856"/>
+						<int key="IBEventType">7</int>
+					</object>
+					<int key="connectionID">40</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">previousQuestionPressed:</string>
+						<reference key="source" ref="356964106"/>
+						<reference key="destination" ref="841351856"/>
+						<int key="IBEventType">7</int>
+					</object>
+					<int key="connectionID">50</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="871929113"/>
+						<reference key="destination" ref="841351856"/>
+						<int key="IBEventType">7</int>
+					</object>
+					<int key="connectionID">39</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="791686696"/>
+						<reference key="destination" ref="841351856"/>
+					</object>
+					<int key="connectionID">57</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="791686696"/>
+						<reference key="destination" ref="841351856"/>
+					</object>
+					<int key="connectionID">58</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBCocoaTouchEventConnection" key="connection">
+						<string key="label">answerChosen:</string>
+						<reference key="source" ref="660724550"/>
+						<reference key="destination" ref="841351856"/>
+						<int key="IBEventType">13</int>
+					</object>
+					<int key="connectionID">89</int>
+				</object>
+			</array>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<array key="orderedObjects">
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<array key="object" id="0"/>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="841351856"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="606714003"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="766721923"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="960474577"/>
+							<reference ref="871929113"/>
+							<reference ref="791686696"/>
+							<reference ref="660724550"/>
+							<reference ref="638395666"/>
+							<reference ref="692955189"/>
+							<reference ref="960632081"/>
+							<reference ref="838658605"/>
+							<reference ref="783180915"/>
+							<reference ref="831894070"/>
+							<reference ref="356964106"/>
+						</array>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="783180915"/>
+						<array class="NSMutableArray" key="children"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="838658605"/>
+						<array class="NSMutableArray" key="children"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="960474577"/>
+						<array class="NSMutableArray" key="children"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="356964106"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="871929113"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">55</int>
+						<reference key="object" ref="791686696"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">63</int>
+						<reference key="object" ref="960632081"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">71</int>
+						<reference key="object" ref="660724550"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">75</int>
+						<reference key="object" ref="638395666"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="340544853"/>
+							<reference ref="316486170"/>
+							<reference ref="674807401"/>
+							<reference ref="85392105"/>
+							<reference ref="36668958"/>
+						</array>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">76</int>
+						<reference key="object" ref="316486170"/>
+						<reference key="parent" ref="638395666"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">77</int>
+						<reference key="object" ref="340544853"/>
+						<reference key="parent" ref="638395666"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">78</int>
+						<reference key="object" ref="674807401"/>
+						<reference key="parent" ref="638395666"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">79</int>
+						<reference key="object" ref="85392105"/>
+						<reference key="parent" ref="638395666"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">80</int>
+						<reference key="object" ref="36668958"/>
+						<reference key="parent" ref="638395666"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">82</int>
+						<reference key="object" ref="692955189"/>
+						<array class="NSMutableArray" key="children">
+							<reference ref="78723594"/>
+							<reference ref="404206660"/>
+							<reference ref="355647270"/>
+							<reference ref="353586444"/>
+							<reference ref="790263268"/>
+						</array>
+						<reference key="parent" ref="766721923"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">87</int>
+						<reference key="object" ref="790263268"/>
+						<reference key="parent" ref="692955189"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">86</int>
+						<reference key="object" ref="353586444"/>
+						<reference key="parent" ref="692955189"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">85</int>
+						<reference key="object" ref="355647270"/>
+						<reference key="parent" ref="692955189"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">84</int>
+						<reference key="object" ref="404206660"/>
+						<reference key="parent" ref="692955189"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">83</int>
+						<reference key="object" ref="78723594"/>
+						<reference key="parent" ref="692955189"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">90</int>
+						<reference key="object" ref="831894070"/>
+						<reference key="parent" ref="766721923"/>
+					</object>
+				</array>
+			</object>
+			<dictionary class="NSMutableDictionary" key="flattenedProperties">
+				<string key="-1.CustomClassName">QuestionnaireViewController</string>
+				<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="-2.CustomClassName">UIResponder</string>
+				<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="55.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="63.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="71.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<integer value="0" key="71.IUISegmentedControlInspectorSelectedSegmentMetadataKey"/>
+				<string key="75.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="76.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="77.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="78.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="79.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="80.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="82.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="83.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="84.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="85.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="86.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="87.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+				<string key="90.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+			</dictionary>
+			<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+			<nil key="activeLocalization"/>
+			<dictionary class="NSMutableDictionary" key="localizations"/>
+			<nil key="sourceID"/>
+			<int key="maxID">91</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<array class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<object class="IBPartialClassDescription">
+					<string key="className">QuestionnaireViewController</string>
+					<string key="superclassName">UIViewController</string>
+					<dictionary class="NSMutableDictionary" key="actions">
+						<string key="answerChosen:">id</string>
+						<string key="hide:">id</string>
+						<string key="nextQuestionPressed:">id</string>
+						<string key="previousQuestionPressed:">id</string>
+						<string key="show:">id</string>
+					</dictionary>
+					<dictionary class="NSMutableDictionary" key="actionInfosByName">
+						<object class="IBActionInfo" key="answerChosen:">
+							<string key="name">answerChosen:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+						<object class="IBActionInfo" key="hide:">
+							<string key="name">hide:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+						<object class="IBActionInfo" key="nextQuestionPressed:">
+							<string key="name">nextQuestionPressed:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+						<object class="IBActionInfo" key="previousQuestionPressed:">
+							<string key="name">previousQuestionPressed:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+						<object class="IBActionInfo" key="show:">
+							<string key="name">show:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+					</dictionary>
+					<dictionary class="NSMutableDictionary" key="outlets">
+						<string key="commentText">UITextView</string>
+						<string key="finishButton">UIButton</string>
+						<string key="interfacePreferenceOptions">UIView</string>
+						<string key="lickertOptions">UIView</string>
+						<string key="nextButton">UIButton</string>
+						<string key="numberChooser">UISegmentedControl</string>
+						<string key="picker">UIPickerView</string>
+						<string key="pleaseAnswer">UILabel</string>
+						<string key="previousButton">UIButton</string>
+						<string key="questionText">UILabel</string>
+						<string key="titleText">UILabel</string>
+					</dictionary>
+					<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<object class="IBToOneOutletInfo" key="commentText">
+							<string key="name">commentText</string>
+							<string key="candidateClassName">UITextView</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="finishButton">
+							<string key="name">finishButton</string>
+							<string key="candidateClassName">UIButton</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="interfacePreferenceOptions">
+							<string key="name">interfacePreferenceOptions</string>
+							<string key="candidateClassName">UIView</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="lickertOptions">
+							<string key="name">lickertOptions</string>
+							<string key="candidateClassName">UIView</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="nextButton">
+							<string key="name">nextButton</string>
+							<string key="candidateClassName">UIButton</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="numberChooser">
+							<string key="name">numberChooser</string>
+							<string key="candidateClassName">UISegmentedControl</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="picker">
+							<string key="name">picker</string>
+							<string key="candidateClassName">UIPickerView</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="pleaseAnswer">
+							<string key="name">pleaseAnswer</string>
+							<string key="candidateClassName">UILabel</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="previousButton">
+							<string key="name">previousButton</string>
+							<string key="candidateClassName">UIButton</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="questionText">
+							<string key="name">questionText</string>
+							<string key="candidateClassName">UILabel</string>
+						</object>
+						<object class="IBToOneOutletInfo" key="titleText">
+							<string key="name">titleText</string>
+							<string key="candidateClassName">UILabel</string>
+						</object>
+					</dictionary>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/QuestionnaireViewController.h</string>
+					</object>
+				</object>
+			</array>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+			<real value="1280" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<string key="IBCocoaTouchPluginVersion">2083</string>
+	</data>
+</archive>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerComms.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,36 @@
+//
+//  ServerComms.h
+//  httpPost
+//
+//  Created by Robert Tubb on 24/02/2013.
+//  Copyright (c) 2013 Robert Tubb. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface ServerComms : NSObject <NSURLConnectionDataDelegate>
+{
+NSURL *serverURL;
+NSString *filePath;
+id delegate;
+SEL doneSelector;
+SEL errorSelector;
+
+BOOL uploadDidSucceed;
+}
+
+-   (id)initWithURL: (NSURL *)serverURL
+           filePath: (NSString *)filePath
+           delegate: (id)delegate
+       doneSelector: (SEL)doneSelector
+      errorSelector: (SEL)errorSelector;
+
+-   (NSString *)filePath;
+
+-(BOOL)doSyncPostRequest:(NSString *)type withData:(NSString *)data;
+-(BOOL)doPostRequest:(NSString *)type withData:(NSString *)data;
+@property (strong,nonatomic) NSMutableData * data;
+@property  BOOL requestInProgress;
+@property (strong, nonatomic) NSString * currentRequestType;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerComms.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,203 @@
+//
+//  ServerComms.m
+//  httpPost
+//
+//  Created by Robert Tubb on 24/02/2013.
+//  Copyright (c) 2013 Robert Tubb. All rights reserved.
+//
+
+#import "ServerComms.h"
+#import "eventLogger.h"
+
+extern EventLogger eventLogger;
+
+@implementation ServerComms
+//
+-(id)init{
+    self = [super init];
+    if(self != nil){
+        self.requestInProgress = NO;
+    }
+    return self;
+}
+//-------------------------------------------------------------------------------
+//  asynchronous one
+-(BOOL)doPostRequest:(NSString *)type withData:(NSString *)data{
+    
+    if(self.requestInProgress){
+        return NO;
+    }
+    self.currentRequestType = type;
+    NSString *localServerURL = @"http://127.0.0.1:8080/newtestservice/";
+    NSString *webServerURL = @"http://www.isophonics.net/tweakathlondatacollector/";
+
+    NSString *urls = [webServerURL stringByAppendingString:type];
+    NSURL *url = [NSURL URLWithString:urls];
+
+
+    // request object
+    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
+    
+    // the data
+    NSString *post = [@"jsontext=" stringByAppendingString:[NSString stringWithFormat:data]];
+    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
+    // length of data
+    NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
+    
+    // request properties/header fields
+    [request setHTTPMethod:@"POST"];
+    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
+    [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
+    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
+    [request setHTTPBody:postData ];
+
+    NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
+    [theConnection release];
+    self.requestInProgress = YES;
+    return YES;
+    //  asynchronous one??
+}
+//--------------------------------------------------------------------
+
+// schncronous
+-(BOOL)doSyncPostRequest:(NSString *)type withData:(NSString *)data{
+    BOOL success;
+    
+    NSString *localServerURL = @"http://127.0.0.1:8080/testservice/";
+    NSString *webServerURL = @"http://www.isophonics.net/datacollector/";
+    
+    NSString *urls = [webServerURL stringByAppendingString:type];
+    NSURL *url = [NSURL URLWithString:urls];
+    
+    
+    // request object
+    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
+    
+    // the data
+    NSString *post = [@"jsontext=" stringByAppendingString:[NSString stringWithFormat:data]];
+    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
+    // length of data
+    NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];
+    
+    // request properties/header fields
+    [request setHTTPMethod:@"POST"];
+    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
+    [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
+    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
+    [request setHTTPBody:postData ];
+    
+    NSURLResponse* response;
+    NSError* error = nil;
+    NSData* result = [NSURLConnection sendSynchronousRequest:request  returningResponse:&response error:&error];
+ 
+    NSString *responseDataString = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
+    
+    //NSString* responseDataString = [NSString stringWithUTF8String: ];
+    NSLog(@"sync req. data %@", responseDataString);
+    [self.data appendData:result];
+    
+    if([responseDataString isEqualToString:@"testConnection:OK"]){
+        
+        eventLogger.testConnectionOK();
+        [responseDataString release];
+        success = true;
+    }else if([responseDataString isEqualToString:@"questionnaire:OK"]){
+        eventLogger.questionnaireOK();
+        success = true;
+    }else    if([responseDataString isEqualToString:@"eventlog:OK"]){
+        // call eventLogger eventlogUploadOK
+        eventLogger.eventlogOK();
+        success = true;
+    }else{
+        success = false;
+        if([type isEqualToString:@"testConnection"]) eventLogger.testConnectionNotOK();
+        if([type isEqualToString:@"eventlog"]) eventLogger.eventlogNotOK();
+        if([type isEqualToString:@"questionnaire"]) eventLogger.questionnaireNotOK();
+    }
+    
+    // else check error??
+    
+    // check result
+    self.requestInProgress = NO;
+    return success;
+}
+//-------------------------------------------------------------------------------------------------
+
+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
+    [self.data setLength:0];
+    NSLog(@"didReceiveResponse : %@",response);
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
+    NSString *responseDataString = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];
+    
+    //NSString* responseDataString = [NSString stringWithUTF8String: ];
+    //NSLog(@" %@ didRecieveData %@",self.currentRequestType, responseDataString);
+    [self.data appendData:d];
+    
+    if([responseDataString isEqualToString:@"testConnection:OK"]){
+
+        eventLogger.testConnectionOK();
+        [responseDataString release];
+    }else if([responseDataString isEqualToString:@"questionnaire:OK"]){
+        eventLogger.questionnaireOK();
+    }else    if([responseDataString isEqualToString:@"eventlog:OK"]){
+        // call eventLogger eventlogUploadOK
+        eventLogger.eventlogOK();
+    }else{
+        if([self.currentRequestType isEqualToString:@"testConnection"]) eventLogger.testConnectionNotOK();
+        if([self.currentRequestType isEqualToString:@"eventlog"]) eventLogger.eventlogNotOK();
+        if([self.currentRequestType isEqualToString:@"questionnaire"]) eventLogger.questionnaireNotOK();
+    }
+}
+//-------------------------------------------------------------------------------
+- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
+
+    NSLog(@"fail with error");
+    if([self.currentRequestType isEqualToString:@"testConnection"]) {
+        UIAlertView * av = [ [UIAlertView alloc] initWithTitle:NSLocalizedString(@"Sorry", @"")
+                                                       message:[error localizedDescription]
+                                                      delegate:nil
+                                             cancelButtonTitle:NSLocalizedString(@"OK", @"")
+                                             otherButtonTitles:nil ];
+        [av show];
+        eventLogger.testConnectionNotOK();
+        
+    }
+    if([self.currentRequestType isEqualToString:@"eventlog"]) eventLogger.eventlogNotOK();
+    if([self.currentRequestType isEqualToString:@"questionnaire"]) eventLogger.questionnaireNotOK();
+    self.requestInProgress = NO;
+    // we won't know what kind of request method this was...
+}
+//-------------------------------------------------------------------------------
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
+    NSString *responseText = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding];
+    
+    // Do anything you want with it
+    NSLog(@"response text: %@",responseText);
+    [responseText release];
+    
+    self.requestInProgress = NO;
+
+}
+//-------------------------------------------------------------------------------
+// Handle basic authentication challenge if needed
+- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
+    NSString *username = @"username";
+    NSString *password = @"password";
+    
+    NSURLCredential *credential = [NSURLCredential credentialWithUser:username
+                                                             password:password
+                                                          persistence:NSURLCredentialPersistenceForSession];
+    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
+}
+/*
+- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse{
+    
+}
+- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{
+    
+}
+*/
+//-------------------------------------------------------------------------------
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SynthParam.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,57 @@
+//
+//  SynthParam.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/10/2014.
+//
+//
+
+#ifndef tweakathlon_SynthParam_h
+#define tweakathlon_SynthParam_h
+
+// class that handles what a synth param "is" , a wrapper for the pd control
+class SynthParam {
+public:
+    static int mappingUID;
+    
+    
+    AppCore* core;
+    SynthParam(int aVal , AppCore* aCore, string aName, string aSynthPrefix){
+        mappingID = mappingUID++;
+        value = aVal;
+        core = aCore;
+        name = aName;
+        synthPrefix = aSynthPrefix;
+        // log the fact that this id is mapped to a certain param?
+    };
+    void setValue(int i){
+        value = i;
+        // TODO should this send an eventlog message? what if called from randomise ? what if different synth?
+        sendToPD();
+    };
+    int getValue() const{
+        return value;
+    }
+    int getID() const {return mappingID;};
+    string getName() const {return name;};
+    void sendToPD() const
+    {
+        // sends this parameter to pd synth
+        List toPD;
+        toPD.addSymbol(synthPrefix);
+        toPD.addSymbol(name);
+        toPD.addFloat(value); // rounding here??
+        
+        core->pd.sendList("fromOF", toPD);
+        //cout << "sending" << synthPrefix << ":" << name << " : " << value << "\n";
+    };
+    
+private:
+    int value; // 0 to 127
+    int mappingID;  // should be globally unique
+    string name; // the string that gets routed in PD, and also the display label (?)
+    string synthPrefix;
+    
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TestController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,657 @@
+//
+//  TestController.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 16/01/2014.
+//
+//
+
+#ifndef __tweakathlon__TestController__
+#define __tweakathlon__TestController__
+
+#include <iostream>
+#include "ofMain.h"
+#include "globalVariables.h"
+#include "boost/foreach.hpp"
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+#include "timeController.h"
+#include <functional>
+#include <algorithm>    // std::transform
+
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+template <class T>
+class randomiseCCVal : public unary_function<T, T>{
+public:
+    T operator()(T a){
+        return ofRandom(0,127);
+        
+    };
+};
+template <class T>
+class randomiseCCValIf : public binary_function<T, bool, T>{
+public:
+    T operator()(T a, bool doit ){
+        if (doit)
+            return ofRandom(0,127);
+        return a;
+        
+    };
+};
+template <class T>
+class printThing : public unary_function<T, void>{
+public:
+    void operator()(T a){
+        cout << a << endl;
+        
+    };
+};
+
+template <class T>
+class difference : public binary_function<T, T, T>{
+public:
+    T operator()(T a, T b ){
+        return abs(a - b);
+    };
+};
+template <class T>
+class squared : public unary_function<T, T>{
+public:
+    T operator()(T a ){
+        return a*a;
+    };
+};
+
+//-------------------------------------------------------------
+
+struct TestResult{
+    float realDistanceToTarget;
+    int targetBandHit; // eg bullseye = 0 edge = 7
+    TimerMillisec timeTaken;
+    int timeWindowHit; // eg < 5s  = 0
+    int dimensionMult;
+    int score;
+    string displayText;
+};
+
+//-------------------------------------------------------------
+// tests, once genrated by the testcontroller get passed around and used to set synths and so on
+//-------------------------------------------------------------
+class Test {
+public:
+    Test(){
+        //?
+        identifyingLetter = '?';
+        timeGiven = 0;
+        panelType= SEQUENTIAL;
+        numDimensions = 0;
+        
+        generateListOfControls();
+        makeRandomTarget();
+        setCandidateToTarget();
+        randomParamSelection(numDimensions);
+        randomiseCandidate();
+        scored = true;
+        withHint = false;
+        memoryTest = false;
+        targetPlaysLeft = 2; // only decr if memory test
+    };
+    // test with random params
+    Test(char letter, int atimeGiven, controlPanelType apanelType, int anumDimensions){
+        // init the stuff
+        //cout << "Making test " << letter << endl;
+        
+        identifyingLetter = letter;
+        timeGiven = atimeGiven;
+        panelType= apanelType;
+        numDimensions = anumDimensions;
+
+        generateListOfControls();
+        makeRandomTarget();
+        setCandidateToTarget();
+        randomParamSelection(numDimensions);
+        randomiseCandidate();
+        scored = true;
+    };
+    // constructor that copies params from other test, pass em in
+    // also serves as a constructor that passes in specific settings
+    Test(char letter, int atimeGiven, controlPanelType apanelType, int anumDimensions, vector<int> aTargetValues, vector<int> aCandidateValues, vector<bool> adjustables){
+        identifyingLetter = letter;
+        timeGiven = atimeGiven;
+        panelType= apanelType;
+        numDimensions = anumDimensions;
+        
+        whichCandidateParamAdjustable = adjustables;
+        generateListOfControls();
+        targetParams = aTargetValues;
+        candidateParams = aCandidateValues;
+        scored = true;
+        
+    }
+    // constructot that enables you to set the space the test is carried out in but not start
+    Test(char letter, int aTimeGiven, controlPanelType pType, int aNumDimensions, vector<bool> adjustables){
+        identifyingLetter = letter;
+        timeGiven = aTimeGiven;
+        panelType= pType;
+        numDimensions = aNumDimensions;
+        
+        generateListOfControls();
+        makeRandomTarget();
+        setCandidateToTarget();
+        whichCandidateParamAdjustable = adjustables;
+        randomiseCandidate();
+        scored = true;
+    }
+    
+
+    
+    // constructor that takes target values, but leaves those not adjustable
+    Test(char letter, int aTimeGiven, controlPanelType pType, int aNumDimensions, vector<bool> adjustables, vector<int> aTargetValues){
+        identifyingLetter = letter;
+        timeGiven = aTimeGiven;
+        panelType= pType;
+        numDimensions = aNumDimensions;
+        
+        generateListOfControls();
+        targetParams = aTargetValues;
+        whichCandidateParamAdjustable = adjustables;
+        randomiseTargetAdjustable();
+        setCandidateToTarget();
+        
+        randomiseCandidate();
+        scored = true;
+    }
+    
+        // the one that is called from generate some tests!!
+    Test(char letter, int aTimeGiven, controlPanelType pType, int aNumDimensions, vector<bool> adjustables, vector<int> aTargetValues, bool ascored = true, bool ahint = false, bool aMemoryTest = false){
+        identifyingLetter = letter;
+        timeGiven = aTimeGiven;
+        panelType= pType;
+        numDimensions = aNumDimensions;
+        
+        generateListOfControls();
+        targetParams = aTargetValues;
+        whichCandidateParamAdjustable = adjustables;
+        randomiseTargetAdjustable();
+        setCandidateToTarget();
+        
+        randomiseCandidate();
+        scored = ascored;
+        withHint = ahint;
+        memoryTest = aMemoryTest;
+        targetPlaysLeft = 1; // only decr if memory test
+    };
+    bool isWithHint(){
+        return withHint;
+    };
+    bool isMemoryTest(){
+        return memoryTest;
+    };
+    bool isPractice(){
+        return !scored;
+    };
+    float euclideanDistance(vector<int> v1, vector<int> v2) const{
+        if (v1.size() != v2.size()){
+            cout << "ERROR ERROR: vectors must be same length for Mr Euclid";
+            return 0.;
+        }
+        vector<float> diff;
+        
+        std::transform(v1.begin(), v1.end(), v2.begin(), v1.begin(), difference<float>());
+        // sqr diff
+        
+        std::transform(v1.begin(), v1.end(), v1.begin(),squared<float>());
+        float ans = std::accumulate(v1.begin(),v1.end(),0.0);
+        
+        return sqrt(ans);
+        
+    };
+    
+    TestResult getScoreForAnswer(vector<int> answer, TimerMillisec timeTaken) const {
+        TestResult result;
+        stringstream msg;
+        int score = 0;
+        // work out euc distance from actual point
+        //for_each(answer.begin(),answer.end(),printThing<int>());
+        //for_each(targetParams.begin(),targetParams.end(),printThing<int>());
+        float dist = euclideanDistance(targetParams, answer);
+        auto dimComp = sqrt(numDimensions);
+        int band = -1;
+        if (dist < TARGET_SCORE_CC_BAND*dimComp){
+            score = 50;
+            band = 1;
+
+            msg << "DOUBLE BULLSEYE!" << endl;
+
+
+        }else if (dist < TARGET_SCORE_CC_BAND*2*dimComp){
+
+            score = 25;
+            band = 2;
+            
+            msg << "SINGLE BULLSEYE!" << endl;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*3*dimComp){
+
+            score = 15;
+            band = 3;
+            msg << "CLOSE..." << endl;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*4*dimComp){
+            score = 5;
+            band = 4;
+            msg << "OK...ISH" << endl;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*6*dimComp){ // 30
+            score = 2;
+            band = 5;
+            msg << "MEDIOCRE" << endl;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*9*dimComp){ // 45
+            score = 1;
+            band = 6;
+            msg << "POOR..." << endl;
+
+        }else{
+            score = 0;
+            band = 7;
+            msg << "MISSED COMPLETELY!" << endl;
+
+            
+        }
+        msg << "Distance from target: " << dist << endl;
+        msg << "Basic Score: " << score << endl;
+        msg << "-----" << endl;
+        msg << "Time taken: " << timeTaken/1000.0 << endl;
+        int window = -1;
+        if (timeTaken < 5000){
+            msg << "Under 5 seconds: 10x bonus" << endl;
+            score *= 10;
+            window = 1;
+        }else if (timeTaken < 10000){
+            msg << "Under 10 seconds: 5x bonus" << endl;
+            score *= 5;
+            window = 2;
+        }else if (timeTaken < 15000){
+            msg << "Under 15 seconds: 3x bonus" << endl;
+            score *=3;
+            window = 3;
+        }else if (timeTaken < 20000){
+            msg << "Under 20 seconds: 2x bonus" << endl;
+            score *=2;
+            window = 4;
+        }else if (timeTaken < 20000){
+            msg << "Under 25 seconds: no bonus" << endl;
+            score *=2;
+            window = 4;
+        }else if (timeTaken > 30000){
+            msg << "Over 30 seconds: TOO LATE!" << endl;
+            score *=0;
+            window = 4;
+        }
+        score *= numDimensions; // dimension bonus
+        msg << numDimensions*numDimensions << "X Dimension bonus" << endl;
+        msg << "-----" << endl;
+        if (!scored){
+            
+            msg << "PRACTICE RUN, scored: " << score << endl;
+            score = 0;
+        }else{
+            msg << "Total: " << score << endl;
+        }
+        result.realDistanceToTarget = dist;
+        result.targetBandHit = band; // eg bullseye = 0 edge = 7
+        result.timeTaken = timeTaken;
+        result.timeWindowHit = window; // eg < 5s  = 0
+        result.dimensionMult = numDimensions*numDimensions;
+        result.score = score;
+        result.displayText = msg.str();
+        
+
+        return result;
+    }
+    
+    vector<int> getChangeableIndices() {
+        vector<int> ids;
+        for(int i=0; i< whichCandidateParamAdjustable.size();i++){
+            if (whichCandidateParamAdjustable[i]){
+                ids.push_back(i);
+            }
+        }
+        return ids;
+    };
+    vector<int> getTargetValues() const{
+        return targetParams;
+        
+    };
+    vector<int> getStartingCandidateValues() const{
+        return candidateParams;
+        
+    };
+
+    int getNumDimensions() const{
+        return numDimensions;
+    }
+    char getTestLetter() const{
+        return identifyingLetter;
+    }
+    vector<bool> getAdjustableMask() const{
+        return whichCandidateParamAdjustable;
+    }
+    vector<controllerType> getListOfControlTypes() const{
+        return listOfControls;
+    }
+    controlPanelType getControlPanelType() const{
+        return panelType;
+    };
+    string getTestTypeAdvanceWarning(){
+        stringstream msg;
+        
+        msg << "Next test: " << endl << endl;
+        if (panelType == REVISITABLE){
+            msg << "Sliders " << " x " << numDimensions << endl;
+        }
+        if (panelType == SIMULTANEOUS && numDimensions == 2){
+            msg << "XY pad " << endl;
+        }
+        if (panelType == SIMULTANEOUS && numDimensions == 3){
+            msg << "LEAP MOTION 3D -> -> -> -> ->" << endl;
+        }
+        if (isMemoryTest()){
+            msg << endl << "MEMORY TEST - ONE TARGET LISTEN ONLY!!" << endl;
+        }
+        if (!scored){
+            msg << "PRACTICE RUN" << endl;
+        }
+        
+        return msg.str();
+    };
+    bool checkTargetPlaysRemaining(){
+        if (isMemoryTest()){
+            targetPlaysLeft--;
+            if (targetPlaysLeft <= 0){
+                return false;
+            }
+        
+        }
+        return true;
+    }
+    int getTargetPlaysLeft(){
+        return targetPlaysLeft;
+    }
+    
+private:
+    char identifyingLetter;
+    int timeGiven;
+    int timeElapsed;
+    controlPanelType panelType;
+    vector<controllerType> listOfControls;
+    int numDimensions;
+    vector<int> targetParams;
+    vector<int> candidateParams;
+    vector<bool> whichCandidateParamAdjustable;
+    int targetPlaysLeft;
+    bool scored, withHint, memoryTest;
+    
+    
+    void setCandidateToTarget(){
+        
+        for(vector<int>::iterator ii = targetParams.begin(); ii < targetParams.end(); ii++){
+            candidateParams.push_back(*ii);
+        }
+    };
+    
+    void generateListOfControls(){
+        // need ?
+        if(panelType == SEQUENTIAL || panelType == REVISITABLE){
+            for(int i=0;i<numDimensions;i++){
+                listOfControls.push_back(SLIDER);
+            }
+        }else{ // panelType == SIMULTANEOUS
+            if(numDimensions == 2){
+                listOfControls.push_back(XYPAD);
+            }
+            if(numDimensions == 3){
+                listOfControls.push_back(LEAP3D);
+
+            }
+            if(numDimensions == 4){
+                listOfControls.push_back(XYPAD);
+                listOfControls.push_back(XYPAD);
+            }
+            
+        }
+    };
+
+    void makeRandomTarget(){
+        targetParams.clear();
+        for(int i=0;i<TOTAL_NUM_PARAMS; i++){
+            int n = ofRandom(0,127); // why does this consistently come out the same??
+            targetParams.push_back(n);
+            
+        }
+  
+    };
+
+    
+    void randomiseCandidate(){
+        // randomises only those who are adjustable
+        // needs to be more than a certain distance (1/3 of total = 40?)
+        float reasonableDistance = 40.0*sqrt(numDimensions);
+        bool notFarEnough = true;
+        while (notFarEnough){
+            transform(candidateParams.begin(),
+                      candidateParams.end(),
+                      whichCandidateParamAdjustable.begin(),
+                      candidateParams.begin(),
+                      randomiseCCValIf<int>());
+            notFarEnough = ( euclideanDistance(candidateParams,targetParams) < reasonableDistance );
+        }
+        cout << "Test distance = " << euclideanDistance(candidateParams,targetParams) << endl;
+        
+    };
+    
+    void randomiseTargetAdjustable(){
+        // randomises only those who are adjustable, in the case where we want exactly the same space
+        // i.e. original target was fed in
+            transform(targetParams.begin(),
+                      targetParams.end(),
+                      whichCandidateParamAdjustable.begin(),
+                      targetParams.begin(),
+                      randomiseCCValIf<int>());
+
+        
+    };
+    
+    // select a few params that will be the ones to chng
+    void randomParamSelection(int numToChange){
+
+        for(int i= 0; i<numToChange; i++){
+            whichCandidateParamAdjustable.push_back(true);
+        }
+        for(int i= 0; i<(TOTAL_NUM_PARAMS - numToChange); i++){
+            whichCandidateParamAdjustable.push_back(false);
+        }
+        random_shuffle(whichCandidateParamAdjustable.begin(), whichCandidateParamAdjustable.end());
+        //for_each(whichCandidateParamAdjustable.begin(), whichCandidateParamAdjustable.end(), printThing<int>());
+        
+    };
+
+    
+};
+//-------------------------------------------------------------
+//-------------------------------------------------------------
+
+
+class TestController {
+public:
+    static const int numDifferentTests;
+    static const int totalNumTests;
+    vector<Test>::iterator currentTest;
+    TestController(){
+        
+       generateSomeTests(1, 3, SIMULTANEOUS,1, false, true, true);
+        
+        generateSomeTests(4, 2, SIMULTANEOUS, 1, true);
+        
+        // 3 demo runs
+        generateSomeTests(1, 1, REVISITABLE, 1, false, false, false);
+        generateSomeTests(1, 2, SIMULTANEOUS, 1, false, false, true);
+        generateSomeTests(1, 3, SIMULTANEOUS,1, false, true, false);
+        // 3 practice runs
+
+        //----------------------
+        // 1D set 1
+        // 7 to 12
+        generateSomeTests(2, 1, REVISITABLE, 1, true);
+        generateSomeTests(2, 1, REVISITABLE, 2, true);
+        generateSomeTests(2, 1, REVISITABLE, 4, true);
+
+        
+        // 2D tests 1
+        // 13 to 28
+        generateSomeTests(4, 2, REVISITABLE, 1, true);
+        generateSomeTests(4, 2, SIMULTANEOUS, 1, true);
+        generateSomeTests(4, 2, SIMULTANEOUS, 2, true);
+        generateSomeTests(4, 2, REVISITABLE, 2, true);
+        
+        // 3D Tests 1
+        // 29 to 44
+        generateSomeTests(8,3,SIMULTANEOUS,1, true);
+        generateSomeTests(8,3,REVISITABLE,1, true);
+        
+        //----------------------
+        
+        // 1D set 2 (WITH HINTS)
+        // 45 to 47
+        generateSomeTests(1, 1, REVISITABLE, 1, true, true);
+        generateSomeTests(1, 1, REVISITABLE, 2, true, true);
+        generateSomeTests(1, 1, REVISITABLE, 4, true, true);
+        
+        // 2D set 2 (WITH HINTS)
+        // 48 to 51
+        generateSomeTests(2, 2, SIMULTANEOUS, 1, true, true);
+        generateSomeTests(2, 2, REVISITABLE, 1, true, true);
+        
+        // 3D set 2 (WITH HINTS)
+        // 52 to 59
+        generateSomeTests(4,3,REVISITABLE ,1, true, true);
+        generateSomeTests(4,3,SIMULTANEOUS,1, true, true);
+        
+        //----------------------
+        
+        // NOW MEMORY TESTS!
+        // 1D memory test
+        generateSomeTests(2, 1, REVISITABLE, 1, true,false, true);
+        generateSomeTests(2, 1, REVISITABLE, 2, true,false, true);
+        generateSomeTests(2, 1, REVISITABLE, 4, true,false, true);
+        
+        // 2D set 3
+        generateSomeTests(4, 2, SIMULTANEOUS, 1, true,false, true);
+        generateSomeTests(4, 2, REVISITABLE, 1, true,false, true);
+        generateSomeTests(4, 2, REVISITABLE, 2, true,false, true);
+        generateSomeTests(4, 2, SIMULTANEOUS, 2, true,false, true);
+        
+       
+        // 3D set 3
+        // MEMORY
+        generateSomeTests(8,3,REVISITABLE ,1, true,false, true);
+        generateSomeTests(8,3,SIMULTANEOUS,1, true,false, true);
+        // 72
+        //----------------------
+
+        
+        
+        //generate1DSpecificTests();
+        
+        //generate2DSpecificTests();
+        //generate3DSpecificTests();
+        //generate2DRandomTests();
+        //generate4DTests();
+        currentTest = testList.begin()-1; // dont do this
+        scoreRunningTotal = 0;
+    };
+
+    
+    bool isLastTest(){
+        if (currentTest == testList.end()-1){
+            return true;
+        }
+        return false;
+    }
+    Test goToNextTest(){
+        
+        if (currentTest < testList.end()-1){
+            currentTest++;
+            cout << "***************** NEXT TEST : " << (*currentTest).getTestLetter() <<  endl;
+            // return a copy
+            // (*currentTest).logThisTestSetup();
+            
+            return *currentTest;
+            
+        }else{
+            cout << "Sequence finished!!!!!!" << endl;
+            Test dummyTest;
+            return dummyTest;
+        }
+    };
+
+    Test getCurrentTest(){
+        // check for valid current test?
+        return *currentTest;
+    }
+    
+    Test* getCurrentTestPtr(){
+        // check for valid current test?
+        if (currentTest < testList.end() && currentTest >= testList.begin()){
+            return &(*currentTest);
+        }else{
+            return NULL;
+        }
+    }
+    //
+    TestResult submitAnswer(vector<int> answer, TimerMillisec timeTaken){
+        TestResult result;
+        result = (*currentTest).getScoreForAnswer(answer, timeTaken);
+        scoreRunningTotal += result.score;
+        return result;
+    }
+    vector<controllerType> getCurrentListOfControls(){
+        return (*currentTest).getListOfControlTypes();
+    }
+    int getScoreRunningTotal(){
+        return scoreRunningTotal;
+    };
+    char getCurrentTestLetter(){
+        return (*currentTest).getTestLetter();
+    };
+    controlPanelType getCurrentPanelType(){
+        return (*currentTest).getControlPanelType();
+    };
+    vector<int> getCurrentChangeableParams(){
+        return (*currentTest).getChangeableIndices();
+    }
+private:
+    void generate2DRandomTests();
+    void generate1DSpecificTests();
+    void generate2DSpecificTests();
+    void generate3DSpecificTests();
+    void generate4DTests();
+    void generateSomeTests(int howManyTests, int dimensions, controlPanelType panelType, int whichSpace, bool scored = true,bool aHint = false, bool aMemoryTest = false);
+    
+    void generateTestSequence(){
+
+    };
+    //aregaergeargera
+    vector<Test> testList;
+
+    long scoreRunningTotal;
+   
+    
+};
+
+
+
+
+#endif /* defined(__tweakathlon__TestController__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TestController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,152 @@
+//
+//  TestController.mm
+//  tweakathlon
+//
+//  Created by Robert Tubb on 16/01/2014.
+//
+//
+
+#include "TestController.h"
+const int TestController::numDifferentTests = 80;
+const int TestController::totalNumTests = 80;
+
+
+template <typename T>
+vector<T> makeVector(T a1, T a2,T a3,T a4,T a5,T a6){
+    
+    vector<T> vec;
+    vec.push_back(a1);
+    vec.push_back(a2);
+    vec.push_back(a3);
+    vec.push_back(a4);
+    vec.push_back(a5);
+    vec.push_back(a6);
+    
+    return vec;
+}
+
+void randomise(int& n){
+    n = ofRandom(0,127);
+    
+}
+
+vector<vector <bool> > makeCombinations(){
+    // make all unordered pairs
+    int N = TOTAL_NUM_PARAMS;
+    
+    vector<vector <bool> > table;
+    for(int n=0; n < N-1; n++){
+        
+        vector<bool> c(6, false);
+        for(int m=n+1; m<N; m++){
+            
+            // reset all to false
+            for(int i=0; i<N; i++){
+                c[i] = false;
+            }
+            
+            c[n] = true;
+            c[m] = true;
+            
+            table.push_back(c);
+            
+        }
+        
+    }
+    return table;
+}
+//----------------------------------------------------------------------------------------
+
+void TestController::generate2DRandomTests(){
+    
+    controlPanelType panelType;
+    int numDimensions = 2;
+    
+    vector<vector <bool> > ap = makeCombinations();
+    // 4 tests for each
+    int testsPerSpace = 2;
+    int numTests = 2 * testsPerSpace * ap.size();
+    int testNum = testList.size();
+    panelType = REVISITABLE;
+    for(int i=0;i<numTests/2; i++){
+        char letter = char(testNum+65);
+        
+        testList.push_back(Test(letter,20, panelType, numDimensions, ap[floor(i/testsPerSpace)]));
+        testNum++;
+    }
+    panelType = SIMULTANEOUS;
+    for(int i=numTests/2+1;i<numTests; i++){
+        char letter = char(i+65);
+        
+        testList.push_back(Test(letter,20, panelType, numDimensions, ap[floor((i-numTests/2)/testsPerSpace)]));
+        
+    }
+};
+//------------------------------------------
+// much better contruction!
+void TestController::generateSomeTests(int howManyTests,
+                                       int numDimensions,
+                                       controlPanelType panelType,
+                                       int whichSpace,
+                                       bool scored,
+                                       bool aHint,
+                                       bool aMemoryTest){
+    int testNum = testList.size();
+    
+    vector<bool> adjustables = makeVector(false, false, false, false, false, false);
+    vector<int> target = makeVector(40,64, 10, 74, 21, 80); // the default target
+    
+    // big if - good spaces for each num of dimensions
+    if(numDimensions == 1){
+        // def 64,64, 30, 55, 42, 43;
+        
+        adjustables[whichSpace-1] = true;
+        
+    }else if(numDimensions == 2){
+        
+        if (whichSpace == 1){
+            target = makeVector(64,64, 30, 55, 40, 43);
+            adjustables[0] = true; // pitch
+            adjustables[3] = true; // decay
+        }else if(whichSpace == 2){
+
+            
+            target = makeVector(64,64, 0, 90, 20, 127);
+            adjustables[3] = true; // decay
+            adjustables[5] = true; // cutoff
+        }else if(whichSpace == 3){
+            target = makeVector(56,64, 20, 64, 10, 90);
+           
+            adjustables[1] = true; // pulse
+            adjustables[2] = true; // attack
+        }else if(whichSpace == 4){
+            target = makeVector(64,64, 0, 55, 40, 43);
+            adjustables[1] = true; // pulse
+            adjustables[4] = true; // ftype
+        }
+    }else if(numDimensions == 3){
+        if(whichSpace == 1){
+            target = makeVector(64,64, 10, 64, 41, 43);
+            adjustables[0] = true; // pitch
+            adjustables[3] = true; // decay
+            adjustables[5] = true; // cutoff
+        }else if(whichSpace == 2){
+            target = makeVector(12,64, 10, 67, 41, 64);
+            adjustables[1] = true; // pulse
+            adjustables[2] = true; // attack
+            adjustables[4] = true; // ftype
+        }
+    }
+    // 4 ???
+    
+    for(int i=0; i < howManyTests; i++){
+        char letter = char(testNum+65);
+        testList.push_back(Test(letter,20, panelType, numDimensions, adjustables, target, scored, aHint, aMemoryTest));
+    }
+}
+
+
+//-------------------------------------------
+void TestController::generate4DTests(){
+    // 4d seq  - learnable??
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TimedCallController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,18 @@
+
+// Super lightweight timer object that is 
+//
+#define SECONDS_PER_INTERFACE 300
+#import <Foundation/Foundation.h>
+
+
+@interface TimedCallController : NSObject <UIAlertViewDelegate>
+@property (nonatomic, assign)       id theOFAppRef;
+@property (nonatomic,strong) NSTimer * theCurrentTimer;
+
+- (void)setAppRef:(id)theOFApp;
+-(void)resetTime:(int)newTime; // if we want to put ourselves somewhen
+-(void)startTimer; // go from start
+-(void)cancelTimers; // stop the whole thing
+-(void)callTheCallback;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TimedCallController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,47 @@
+//
+//  TimedSessionController.m
+//  sonicZoom
+//
+//  Created by Robert Tubb on 18/02/2013.
+//
+//
+
+#import "TimedCallController.h"
+@interface TimedCallController()
+    // private stuff
+@end
+
+@implementation TimedCallController
+
+
+// nicer if it was initWithAppRef ?
+- (void)setAppRef:(id)theOFApp{
+    self.theOFAppRef = theOFApp;
+
+}
+-(void)startTimer{
+
+}
+-(void)resetTime:(int)newTime{
+    
+}
+
+
+-(void)cancelTimers{
+
+    if(self.theCurrentTimer){
+        [self.theCurrentTimer invalidate];
+        self.theCurrentTimer = nil;
+    }
+}
+
+-(void)setTimer:(int)numMillisec{
+    self.theCurrentTimer = [NSTimer scheduledTimerWithTimeInterval:numMillisec target:self selector:@selector(callTheCallback) userInfo:nil repeats:NO];
+
+}
+-(void)callTheCallback{
+    NSLog(@"iostimer callback");
+}
+
+
+@end
Binary file UI code/.DS_Store has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/3Dbox.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,185 @@
+//
+//  3Dbox.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 13/02/2014.
+//
+//
+
+#ifndef __tweakathlon___Dbox__
+#define __tweakathlon___Dbox__
+
+#include <iostream>
+#include "UIElement.h"
+#include "ofMain.h"
+
+
+class Leap3DBox : public UIElement {
+    
+public:
+    Leap3DBox(float ax,
+              float ay,
+              float awidth,
+              float aheight,
+              float azx,
+              float azy,
+              const UIProps& props);
+    void init(const UIProps& props);
+    
+    void setValueAndScale(int which, int val){
+        if(which == 0)      xVal =  (val - minVal)/(maxVal - minVal);
+        if(which == 1)      yVal =  (val - minVal)/(maxVal - minVal);
+        if(which == 2)      zVal =  (val - minVal)/(maxVal - minVal);
+        //cout << zVal << endl;
+    }
+    
+    void setHintValue(int which, int val){
+        if(which == 0)      hintX =  (val - minVal)/(maxVal - minVal);
+        if(which == 1)      hintY =  (val - minVal)/(maxVal - minVal);
+        if(which == 2)      hintZ =  (val - minVal)/(maxVal - minVal);
+        
+    };
+
+    void draw(){
+        if(hidden)return;
+        if(on){
+            ofSetColor(foregroundHi);
+        }else{
+            ofSetColor(foregroundLo);
+            
+        }
+        if(inactive){
+            ofSetColor(fgInactive);
+        }
+        
+
+        // draw rear face zy+
+        ofLine(zx+x,zy+y,zx+x,zy+y+height); // left
+        ofLine(zx+x,zy+y,zx+x+width,zy+y); // top
+        ofLine(zx+x+width,zy+y,zx+x+width,zy+y+height); //right
+        ofLine(zx+x+width,zy+y+height,zx+x,zy+y+height); // bottom
+        
+        // draw indicators
+        drawIndicator();
+        
+        ofSetColor(foregroundHi);
+        
+        // draw connectors
+        ofLine(x,y,zx+x,zy+y); // top left
+        ofLine(x+width,y,zx+x+width,zy+y); // top right
+        ofLine(x,y+height,zx+x,zy+y+height); // bot left
+        ofLine(x+width,y+height,zx+x+width,zy+y+height); // bot right
+
+        
+        // draw front face
+        ofLine(x,y,x,y+height); // left
+        ofLine(x,y,x+width,y); // top
+        ofLine(x+width,y,x+width,y+height); //right
+        ofLine(x+width,y+height,x,y+height); // bottom
+        
+        drawLabels();
+        
+    };
+    
+    void drawLabels(){
+        ofColor fg,bg;
+        
+        if(on){
+            fg = foregroundHi;
+            bg = backgroundHi;
+        }else{
+            fg = foregroundLo;
+            bg = backgroundLo;
+        }
+        if(inactive){
+            fg = fgInactive;
+        }
+        ofSetColor(fg);
+        verdana16.drawString(labelNameX + " (L/R)", ofGetWidth()/2 - 120, y + height + 50 );
+        verdana16.drawString(labelNameY + " (Up/Dn)", ofGetWidth()/2 - width + 50, y + height/2 );
+        verdana16.drawString(labelNameZ + " Fwd/Bck)", ofGetWidth()/2 + width - 20, y+height);
+        
+        // TODO up down etc
+    };
+    void setLabels(string ax, string ay, string az){
+        labelNameX = ax;
+        labelNameY = ay;
+        labelNameZ = az;
+    }
+    
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        return false;
+    };
+    void showHint(bool show){
+        hintShowing = show;
+    }
+    void setHintColor(ofColor c){
+        hintColor = c;
+    };
+
+protected:
+    void drawIndicator(){
+        ofSetColor(foregroundHi);
+        float px,py;
+        px = x + xVal*width + zx*zVal;
+        py = y + (1-yVal)*height + zy*zVal;
+        
+        // line to left wall (no x)
+        ofLine(px , py , x+zx*zVal, py);
+        
+        ofEllipse(px,py,thickness,thickness);
+        
+
+        // line to bottom wall (no y)
+        ofLine(px , py , px, y+height+zy*zVal);
+        // line to front wall ( no z)
+        ofLine(px , py , x+ width*xVal, y + height*(1-yVal));
+
+        if(hintShowing) drawHintIndicator();
+    };
+    void drawHintIndicator(){
+        ofSetColor(hintColor);
+        float px,py;
+        px = x + hintX*width + zx*hintZ;
+        py = y + (1-hintY)*height + zy*hintZ;
+        
+        // line to left wall (no x)
+        ofLine(px , py , x+zx*hintZ, py);
+        
+        ofEllipse(px,py,thickness,thickness);
+        
+        
+        // line to bottom wall (no y)
+        ofLine(px , py , px, y+height+zy*hintZ);
+        // line to front wall ( no z)
+        ofLine(px , py , x+ width*hintX, y + height*(1-hintY));
+    
+    };
+    
+
+    float xVal,yVal,zVal;
+    float zx,zy; // how much of z and x shows up in diagonal x and y
+    
+    
+    float minVal;
+    float maxVal;
+    
+    
+    float hintX;
+    float hintY;
+    float hintZ;
+    bool hintShowing;
+    
+    string labelNameX;
+    string labelNameY;
+    string labelNameZ;
+    
+    float thickness; // width of border and indicator
+    ofColor foregroundHi;
+    ofColor backgroundHi;
+    ofColor foregroundLo;
+    ofColor backgroundLo;
+    ofColor fgInactive;
+    ofColor hintColor;
+};
+#endif /* defined(__tweakathlon___Dbox__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/3Dbox.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,42 @@
+//
+//  3Dbox.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 13/02/2014.
+//
+//
+
+#include "3Dbox.h"
+
+Leap3DBox::Leap3DBox(float ax,
+          float ay,
+          float awidth,
+          float aheight,
+          float azx,
+          float azy,
+          const UIProps& props) :
+UIElement(ax,ay,awidth, aheight, props)
+{
+    zx = azx;
+    zy = -azy; // cos of stoopid screen coords
+    init(props);
+}
+
+void Leap3DBox::init(const UIProps& props){
+    minVal = 0.;
+    maxVal = 127.;
+    xVal = 0.1;
+    yVal = 0.1;
+    zVal = 0.1;
+    
+    thickness = props.borderThickness;
+    foregroundHi = props.buttonHi;
+    backgroundHi = props.generalBackground;
+    foregroundLo = props.buttonLo;
+    backgroundLo = props.generalBackground;
+    fgInactive = props.inactiveGreyedOut;
+    hintShowing = false;
+    on = false;
+    
+    myType = LEAP3D;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/3DboxGL.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,232 @@
+//
+//  3DboxGL.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 17/04/2014.
+//
+// same as 3d biox but with better 3d visualisation
+
+#ifndef __tweakathlon___DboxGL__
+#define __tweakathlon___DboxGL__
+
+#include <iostream>
+#include "3Dbox.h"
+#include "UIElement.h"
+
+#endif /* defined(__tweakathlon___DboxGL__) */
+
+//Universal function which sets normals for the triangle meshvoid
+void setNormals( ofMesh &mesh );
+
+float euclideanDistance(vector<float> v1, vector<float> v2);
+
+class Leap3DBoxGL : public Leap3DBox {
+public:
+    Leap3DBoxGL(float ax,
+              float ay,
+              float awidth,
+              float aheight,
+              float azx,
+              float azy,
+              const UIProps& props);
+    
+    void draw(){
+        if(hidden)return;
+        if(on){
+            ofSetColor(foregroundHi);
+        }else{
+            ofSetColor(foregroundLo);
+            
+        }
+        if(inactive){
+            ofSetColor(fgInactive);
+        }
+
+        
+        
+        ofPushMatrix();
+        ofDisableAlphaBlending();
+        ofEnableDepthTest();
+        // move to correct pos
+        
+        ofTranslate( x+width/2, y+height/2, camTrans);
+        ofRotate( angleX, 1, 0, 0 );
+        ofRotate( angleY, 0, 1, 0 );
+
+        setNormals(boxMesh);
+        ofSetColor(foregroundHi);
+        boxMesh.draw();
+        
+                 // draw indicators
+        drawIndicator();
+        ofPopMatrix();
+        
+        drawLabels();
+    };
+    
+    void drawIndicator(){
+
+        if (hintShowing && (hintZ > zVal)){
+            hintColor = calculateHintColor();
+            draw3DCrossHairs(hintX, hintY, hintZ,hintColor);
+            
+        }
+        
+        // draw indicator
+        draw3DCrossHairs(xVal,yVal,zVal, indicatorColor);
+        // put light in indicateor
+        //
+        
+        
+        if (hintShowing && hintZ <= zVal){
+            hintColor = calculateHintColor();
+            draw3DCrossHairs(hintX, hintY, hintZ,hintColor);
+            
+        }
+    }
+    void draw3DCrossHairs(float x , float y, float z, ofColor c){
+        
+        float ix = x*width - width/2;
+        float iy = (1-y)*width - width/2;
+        float iz = (1-z)*width - width/2;
+        
+        float left = - width/2;
+        float bot = width/2;
+        float front = width/2;
+        //
+        ofSetColor(c);
+        ofSetLineWidth(2.);
+        // line to bottom
+        ofLine(ix,iy,iz,ix,bot,iz);
+        // line to left
+        ofLine(ix,iy,iz,left,iy,iz);
+
+        //blob
+        ofDrawIcoSphere(ix,iy,iz,12);
+        // line to front (a bit wierd?)
+        ofLine(ix,iy,iz,ix,iy,front);
+        
+
+        
+    }
+    ofColor calculateHintColor(){
+
+        
+        // this is all duplicate code and may change so a bit bad >:(
+        float dist = sqrt( 127.*127.*((xVal - hintX)*(xVal - hintX) + (yVal - hintY)*(yVal - hintY) + (zVal - hintZ)*(zVal - hintZ)) );
+        
+        auto dimComp = sqrt(3.0);
+        int band = -1;
+        if (dist < TARGET_SCORE_CC_BAND*dimComp){
+
+            band = 1;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*2*dimComp){
+
+            band = 2;
+
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*3*dimComp){
+
+            band = 3;
+
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*4*dimComp){
+
+            band = 4;
+
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*6*dimComp){ // 30
+
+            band = 5;
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*9*dimComp){ // 45
+            band = 6;
+            
+        }else{
+            band = 7;
+ 
+        }
+
+        
+        ofColor c;
+        if(band == 1){
+            // yellow red blue
+            c = ofColor(255,255,0,255);
+        }else if(band == 2){
+            c = ofColor(255,0,0,255);
+        }else if(band == 3){
+            c = ofColor(45,45,255,255);
+        }else if(band == 4){
+            c = ofColor(0,255,0,255);
+        }else{
+            c = ofColor(150,235,200,255);
+        }
+        return c;
+        
+    }
+    void drawCylinders(){
+        ofPushMatrix();
+        ofTranslate( x, y, camTrans);
+        // vertical
+        ofSetColor(0,255,0);
+        ofDrawCylinder(0, 0, 32, 500*yVal);
+        
+        // into screen
+        ofSetColor(255,0,0);
+        ofRotate( 90, 1, 0, 0 );
+        ofDrawCylinder(70, 0, 32, 500*zVal);
+        ofRotate( -90, 1, 0, 0 );
+        // l/r horizona
+        ofSetColor(0,0,255);
+        ofRotate( 90, 0, 0, 1 );
+        ofDrawCylinder(70, 300, 32, 500*xVal);
+        
+        
+        ofPopMatrix();
+    }
+    float valToScreen(float val){
+        float sc;
+        return sc;
+    };
+    
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        static float lastTX = 0.,lastTY = 0.;
+
+
+        if (ttype == TOUCH_MOVED && touchID == 0){
+            float dx = x -lastTX;
+            float dy = y - lastTY;
+            
+            angleY += dx/3;
+            angleX += dy/3;
+
+        }
+        
+        if (ttype == TOUCH_MOVED && touchID == 1){
+            float dx = x -lastTX;
+            float dy = y - lastTY;
+            
+            // adjust light angle?
+            angleY += dx/3;
+            angleX += dy/3;
+            
+        }
+        
+        //cout << angleX << " : " << angleY << endl;
+        
+        lastTX = x;
+        lastTY = y;
+        return true;
+
+    };
+    
+    float angleX;
+    float angleY;
+    float depth;
+    ofMesh boxMesh;
+    float camTrans;
+    ofColor indicatorColor;
+    
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/3DboxGL.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,157 @@
+//
+//  3DboxGL.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 17/04/2014.
+//
+//
+
+#include "3DboxGL.h"
+
+
+Leap3DBoxGL::Leap3DBoxGL(float ax,
+                         float ay,
+                         float awidth,
+                         float aheight,
+                         float azx,
+                         float azy,
+                         const UIProps& props) :
+Leap3DBox(ax,ay,awidth, aheight, azx, azy, props)
+{
+    indicatorColor = ofColor(123, 123, 220);
+    // how much to rotate the box
+    angleX = -25;
+    angleY = -24;
+    
+    depth = width; // its a cube
+    
+    // where is the camera
+    camTrans = 0;
+    
+    // cube is centred on 0,0,0
+    float I = width/2;
+    float O = -width/2;
+    
+    // left face x=O
+    // back face z=O
+    // top face y=O
+    
+    // positions of vertices
+    ofPoint ltf = ofPoint( O,O,I );
+    ofPoint lbf = ofPoint( O,I,I );
+    ofPoint rtf = ofPoint( I,O,I );
+    ofPoint rbf = ofPoint( I,I,I );
+    
+    ofPoint ltr = ofPoint( O,O,O );
+    ofPoint lbr = ofPoint( O,I,O );
+    ofPoint rtr = ofPoint( I,O,O );
+    ofPoint rbr = ofPoint( I,I,O );
+    
+    // now build faces
+    // rear
+    boxMesh.addVertex(ltr);
+    boxMesh.addVertex(rtr);
+    boxMesh.addVertex(rbr);
+    
+    boxMesh.addVertex(ltr);
+    boxMesh.addVertex(rbr);
+    boxMesh.addVertex(lbr);
+    
+    // left
+    boxMesh.addVertex(ltf);
+    boxMesh.addVertex(ltr);
+    boxMesh.addVertex(lbr);
+    
+    boxMesh.addVertex(ltf);
+    boxMesh.addVertex(lbr);
+    boxMesh.addVertex(lbf);
+    
+    // bottom
+    boxMesh.addVertex(lbf);
+    boxMesh.addVertex(lbr);
+    boxMesh.addVertex(rbr);
+    
+    boxMesh.addVertex(lbf);
+    boxMesh.addVertex(rbr);
+    boxMesh.addVertex(rbf);
+    
+    // top
+//    boxMesh.addVertex(ltr);
+//    boxMesh.addVertex(rtr);
+//    boxMesh.addVertex(rtf);
+//    
+//    boxMesh.addVertex(ltr);
+//    boxMesh.addVertex(rtf);
+//    boxMesh.addVertex(ltf);
+//    
+//    // right
+//    boxMesh.addVertex(rtf);
+//    boxMesh.addVertex(rtr);
+//    boxMesh.addVertex(rbr);
+//    
+//    boxMesh.addVertex(rtf);
+//    boxMesh.addVertex(rbr);
+//    boxMesh.addVertex(rbf);
+    
+    // front
+//    boxMesh.addVertex(ltr);
+//    boxMesh.addVertex(rtr);
+//    boxMesh.addVertex(rbr);
+//    
+//    boxMesh.addVertex(ltr);
+//    boxMesh.addVertex(rbr);
+//    boxMesh.addVertex(lbr);
+    
+    boxMesh.setupIndicesAuto();
+}
+
+
+//--------------------------------------------------------------
+
+void setNormals( ofMesh &mesh )
+
+{
+    //The number of the vertices
+    int nV = mesh.getNumVertices();
+    
+    //The number of the triangles
+    int nT = mesh.getNumIndices() / 3;
+    
+    vector<ofPoint> norm( nV );
+    
+    //Array for the normals
+    //Scan all the triangles. For each triangle add its
+    //normal to norm's vectors of triangle's vertices
+    
+    for (int t=0; t<nT; t++) {
+        //Get indices of the triangle t
+        int i1 = mesh.getIndex( 3 * t );
+        int i2 = mesh.getIndex( 3 * t + 1 );
+        int i3 = mesh.getIndex( 3 * t + 2 );
+        
+        //Get vertices of the triangle
+        const ofPoint &v1 = mesh.getVertex( i1 );
+        const ofPoint &v2 = mesh.getVertex( i2 );
+        const ofPoint &v3 = mesh.getVertex( i3 );
+        
+        //Compute the triangle's normal
+        ofPoint dir = ( (v2 - v1).crossed( v3 - v1 ) ).normalized();
+        
+        //Accumulate it to norm array for i1, i2, i3
+        norm[ i1 ] += dir;
+        norm[ i2 ] += dir;
+        norm[ i3 ] += dir;
+    }
+    //Normalize the normal's length
+    for (int i=0; i<nV; i++)
+    {
+        norm[i].normalize();
+        
+    }
+    //Set the normals to mesh
+    mesh.clearNormals();
+    mesh.addNormals( norm );
+}
+
+// algs
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/Buttron.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,81 @@
+//
+//  buttron.h
+//  emptyExample
+//
+//  Created by Robert Tubb on 30/04/2013.
+//
+//
+
+
+// this is a rectangualr thingy with border and on/off functionality
+
+#ifndef __emptyExample__buttron__
+#define __emptyExample__buttron__
+
+#include <iostream>
+#include "ofMain.h"
+#include "UIElement.h"
+#include "UIProperties.h"
+
+class Buttron : public UIElement{
+    
+public:
+    typedef enum {TOGGLE,MOMENTARY} Mode; // should be in subclasss
+
+    float thickness; // width of border
+    float radius;   // inner radius of corners, reccomended to be same as thickness
+    ofColor foregroundHi;
+    ofColor backgroundHi;
+    ofColor foregroundLo;
+    ofColor backgroundLo;
+    ofColor fgInactive;
+    
+    bool pressed; // on and pressed can be different
+    
+    Buttron();
+    ~Buttron(){};
+    
+    // this constructor sets up with defaults obtained from UIProperties (recoomemnded)
+    Buttron(float x,
+            float y,
+            const UIProps& props
+            );
+    Buttron(float x,
+            float y,
+            float width,
+            float height,
+            const UIProps& props
+            );
+    Buttron(float x,
+            float y,
+            float width,
+            float height,
+            const UIProps& props,
+            Mode mode
+            );
+    
+    Buttron(float x,
+            float y,
+            float width,
+            float height,
+            float thickness,
+            float radius,
+            ofColor foregroundHi,
+            ofColor backgroundHi,
+            ofColor foregroundLo,
+            ofColor backgroundLo);
+    void draw();
+    void drawOutline();
+    void drawTextLabel();
+    void setMode(Mode m){
+        behaviourMode = m;
+    };
+    virtual bool handleMyTouch(int x, int y, touchType ttype, int touchID);
+
+protected:
+    Mode behaviourMode;
+    
+};
+
+
+#endif /* defined(__emptyExample__buttron__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/Buttron.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,179 @@
+//
+//  buttron.cpp
+//  emptyExample
+//
+//  Created by Robert Tubb on 30/04/2013.
+//
+//
+
+#include "buttron.h"
+
+//------------------------------------------------------------------
+
+Buttron::Buttron(){
+    //
+    //cout << " buttron default constructur\n";
+}
+//------------------------------------------------------------------
+Buttron::Buttron(
+        float ax,
+        float ay,
+        float awidth,
+        float aheight,
+        float athickness,
+        float aradius,
+        ofColor aforegroundHi,
+        ofColor abackgroundHi,
+        ofColor aforegroundLo,
+        ofColor abackgroundLo) :
+        UIElement(ax,ay,awidth,aheight,abackgroundLo),
+        thickness(athickness),
+        radius(aradius),
+        foregroundHi(aforegroundHi),
+        backgroundHi(abackgroundHi),
+        foregroundLo(aforegroundLo),
+        backgroundLo(abackgroundLo) {
+    //cout << "phew, buttron big constructur\n";
+    on = false;
+}
+//------------------------------------------------------------------
+Buttron::Buttron(float ax,
+                 float ay,
+                 const UIProps& props):
+        UIElement(ax,ay,props.buttonWidth,props.buttonHeight, props)
+
+{
+
+    thickness = props.borderThickness;
+    radius = props.cornerRadius;
+    foregroundHi = props.buttonHi;
+    backgroundHi = props.generalBackground;
+    foregroundLo = props.buttonLo;
+    backgroundLo = props.generalBackground;
+    
+    on = false;
+}
+//------------------------------------------------------------------
+Buttron::Buttron(float ax,
+        float ay,
+        float awidth,
+        float aheight,
+        const UIProps& props):
+    UIElement(ax,ay,awidth,aheight, props)
+
+{
+    //cout << "slider (meh) recommended constructor\n";
+    
+    thickness = props.borderThickness;
+    radius = props.cornerRadius;
+    foregroundHi = props.buttonHi;
+    backgroundHi = props.generalBackground;
+    foregroundLo = props.buttonLo;
+    backgroundLo = props.generalBackground;
+    fgInactive = props.inactiveGreyedOut;
+    
+    on = false;
+}
+//------------------------------------------------------------------
+void Buttron::draw(){
+    if(hidden) return;
+    //cout << "drawing button" << endl;
+    ofFill();
+    UIElement::draw(); // should do background
+    drawOutline();
+    drawTextLabel();
+}
+//------------------------------------------------------------------
+void Buttron::drawTextLabel(){
+    ofColor fg,bg;
+    
+    if(on){
+        fg = foregroundHi;
+        bg = backgroundHi;
+    }else{
+        fg = foregroundLo;
+        bg = backgroundLo;
+    }
+    if(inactive){
+        fg = fgInactive;
+    }
+    ofSetColor(fg);
+    verdana16.drawString(labelName, x + thickness*2, y + 35);
+    
+}
+//------------------------------------------------------------------
+void Buttron::drawOutline(){
+    
+    // draw bars
+    ofColor fg,bg;
+    
+    if(on){
+        fg = foregroundHi;
+        bg = backgroundHi;
+    }else{
+        fg = foregroundLo;
+        bg = backgroundLo;
+    }
+    ofSetColor(fg);
+    
+    float cornerSize = thickness + radius;
+    // left
+    ofRect(x, y+cornerSize, thickness, height - 2*(cornerSize));
+    //right
+    ofRect(x + width - thickness, y+cornerSize, thickness, height - 2*(cornerSize));
+    // top
+    ofRect(x+cornerSize, y, width-2*(cornerSize), thickness);
+    // bottom
+    ofRect(x+cornerSize, y+height-thickness, width-2*(cornerSize), thickness);
+    
+    // draw corner  foreground circles
+    
+    //tl
+    ofCircle(x+cornerSize, y+cornerSize, cornerSize);
+
+    
+    //tr
+
+    ofCircle(x+width-cornerSize, y+cornerSize, cornerSize);
+
+    //bl
+
+    ofCircle(x+cornerSize, y+height-cornerSize, cornerSize);
+
+    //br
+
+    ofCircle(x+width-cornerSize, y+height-cornerSize, cornerSize);
+
+    // draw corner inner bg circles
+    ofSetColor(bg);
+    ofCircle(x+cornerSize, y+cornerSize, radius);
+
+    ofCircle(x+width-cornerSize, y+cornerSize, radius);
+
+    ofCircle(x+cornerSize, y+height-cornerSize, radius);
+
+    ofCircle(x+width-cornerSize, y+height-cornerSize, radius);
+    
+    // fill in background
+    ofRect(x+cornerSize,y+thickness,width-2*cornerSize,height-2*thickness);
+    ofRect(x+thickness, y+cornerSize, radius, height-2*cornerSize);
+    ofRect(x+width-cornerSize, y+cornerSize, radius, height-2*cornerSize);
+}
+//------------------------------------------------------------------------------
+bool Buttron::handleMyTouch(int tx, int ty, touchType ttype, int touchID){
+    
+    //cout << "buttron handling touch\n";
+    if(ttype == TOUCH_DOWN){
+        on = true;
+        if(callback) callback(myParamID,1);
+        
+    }else if(ttype == TOUCH_MOVED){
+        
+    }else if(ttype == TOUCH_UP){
+        on = false;
+    }
+    return true; // necessary?
+    
+}
+
+//------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/ButtronSlider.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,82 @@
+//
+//  ButtronSlider.h
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#ifndef __emptyExample__ButtronSlider__
+#define __emptyExample__ButtronSlider__
+#include "Buttron.h"
+#include <iostream>
+
+class ButtronSlider : public Buttron{
+public:
+
+    ~ButtronSlider(){};
+    ButtronSlider(float ax,
+                  float ay,
+                  float awidth,
+                  float aheight,
+                  float athickness,
+                  float aradius,
+                  ofColor aforegroundHi,
+                  ofColor abackgroundHi,
+                  ofColor aforegroundLo,
+                  ofColor abackgroundLo,
+                  SliderType type);
+    
+    ButtronSlider(float ax,
+                  float ay,
+                  float awidth,
+                  float aheight,
+                  SliderType type,
+                  const UIProps& props);
+    
+    void init();
+    void draw(){
+        Buttron::draw();
+        drawIndicator(value);
+        if(hintShowing) drawHintIndicator();
+    }
+    
+    void setHintValue(double hval){
+        hintValue = (hval - minVal)/(maxVal - minVal);
+    };
+    void setHintColor(ofColor c){
+        hintColor = c;
+    };
+    void showHint(bool tf){
+        hintShowing = tf;
+    };
+    void setValue(double avalue){
+        // scale appropriately to 0-1   (maxVal - minVal)*prop + minVal
+        value = avalue; // (avalue - minVal)/(maxVal - minVal);
+    };
+    
+    void setValueAndScale(double avalue){
+        // scale appropriately to 0-1   (maxVal - minVal)*prop + minVal
+        value =  (avalue - minVal)/(maxVal - minVal);
+    };
+
+    virtual bool handleMyTouch(int x, int y, touchType ttype, int touchID);
+    
+    void setRange(float lo, float hi){
+        minVal = lo;
+        maxVal = hi;
+    }
+    
+private:
+    void drawIndicator(double proportion);
+    float minVal;
+    float maxVal;
+    void drawHintIndicator();
+    SliderType sliderType;
+    float value; // [0. 1.]
+    float hintValue;
+    bool hintShowing;
+    ofColor hintColor;
+};
+
+#endif /* defined(__emptyExample__ButtronSlider__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/ButtronSlider.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,106 @@
+//
+//  ButtronSlider.cpp
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#include "ButtronSlider.h"
+
+
+ButtronSlider::ButtronSlider(float ax,
+                             float ay,
+                             float awidth,
+                             float aheight,
+                             float athickness,
+                             float aradius,
+                             ofColor aforegroundHi,
+                             ofColor abackgroundHi,
+                             ofColor aforegroundLo,
+                             ofColor abackgroundLo,
+                             SliderType type) :
+Buttron(ax,ay,awidth,aheight,athickness,aradius,aforegroundHi,abackgroundHi,aforegroundLo,abackgroundLo),
+sliderType(type)
+
+{
+
+    init();
+}
+ButtronSlider::ButtronSlider(float ax,
+                             float ay,
+                             float awidth,
+                             float aheight,
+                             SliderType type,
+                             const UIProps& props) :
+Buttron(ax,ay,awidth,aheight,props),
+sliderType(type)
+
+{
+    init();
+}
+void  ButtronSlider::init(){
+    myType = SLIDER;
+    minVal = 0.;
+    maxVal = 127.;
+    value = 0.6;
+    hintShowing = false;
+}
+// 
+//---------------------------------------------------------------------
+void ButtronSlider::drawIndicator(double proportion){
+    if(on){
+        ofSetColor(foregroundHi);
+    }else{
+        ofSetColor(foregroundLo);
+        
+    }
+    if(inactive){
+        ofSetColor(fgInactive);
+    }
+    if(sliderType == FILL){
+
+        double maxH = height - 2 * thickness; //
+        double w = width - 2 * thickness;//
+        double barheight = value*maxH;
+        double top = y + height - thickness - barheight;
+        ofRect(x+thickness, top, w, barheight);
+        
+    }else if(sliderType == LINE){
+        double loc = y + thickness +  (1 -value)*(height-3*thickness);
+        ofRect(x+thickness,loc, width-2*thickness,thickness);
+    }
+    
+
+}
+
+void ButtronSlider::drawHintIndicator(){
+
+    ofSetColor(hintColor);
+    float hthick = 1;
+    double loc = y + hthick +  (1 - hintValue)*(height-3*hthick);
+    ofRect(x+thickness,loc, width-2*thickness,hthick);
+
+}
+
+//---------------------------------------------------------------------
+
+bool ButtronSlider::handleMyTouch(int tx, int ty, touchType ttype, int touchID){
+
+    double ly = ty - y - thickness - radius;
+    
+    double prop;
+    
+    prop = 1 - ly/(height - 2 * (thickness + radius));
+
+    if(prop > 1.) prop = 1.;                                                           
+    if(prop < 0.) prop = 0.;
+
+    setValue(prop);
+    int scaleVal = int((maxVal - minVal)*prop + minVal);
+
+    vector<int> pass;
+    if(callback) callback(myParamID,scaleVal);
+    
+    return true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/ButtronXY.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,109 @@
+//
+//  ButtronXY.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 25/06/2013.
+//
+//
+
+#ifndef __tweakathlon__ButtronXY__
+#define __tweakathlon__ButtronXY__
+
+#include <iostream>
+#include "buttron.h"
+
+class ButtronXY: public Buttron {
+    
+public:
+    
+    UICallbackFunction callback;
+    
+    double xvalue, yvalue; // [0. 1.]
+    ~ButtronXY(){};
+    ButtronXY(float ax,
+              float ay,
+              const UIProps& props);
+    ButtronXY(float ax,
+                  float ay,
+                  float awidth,
+                  float athickness,
+                  float aradius,
+                  ofColor aforegroundHi,
+                  ofColor abackgroundHi,
+                  ofColor aforegroundLo,
+                  ofColor abackgroundLo);
+    
+    void draw(){
+        if(hidden) return;
+        Buttron::draw();
+        drawIndicator();
+        drawLabels();
+    }
+    void drawLabels(){
+        // where?
+        ofColor fg,bg;
+        
+        if(on){
+            fg = foregroundHi;
+            bg = backgroundHi;
+        }else{
+            fg = foregroundLo;
+            bg = backgroundLo;
+        }
+        ofSetColor(fg);
+        verdana16.drawString(labelNamex, x + width/2, y + thickness*4);
+        verdana16.drawString(labelNamey,   x + thickness*2, y + height/2+7);
+    }
+    void init();
+    
+    void setValue(double axvalue, double ayvalue){
+        xvalue = axvalue;
+        yvalue = ayvalue;
+    };
+    void setValueAndScale(double axvalue, double ayvalue){
+        xvalue =  (axvalue - minVal)/(maxVal - minVal);
+        yvalue =  (ayvalue - minVal)/(maxVal - minVal);
+    }
+    void setHintValue(double hvalx, double hvaly){
+        hintValuex = (hvalx - minVal)/(maxVal - minVal);
+        hintValuey = (hvaly - minVal)/(maxVal - minVal);
+        
+    };
+    void setHintColor(ofColor c){
+        // TODO somehow set the fill ? 
+    };
+    void setLabel(string xlabel, string ylabel){
+        labelNamex = xlabel;
+        labelNamey = ylabel;
+    }
+
+    
+    void showHint(bool tf){
+        hintShowing = tf;
+    };
+    virtual bool handleMyTouch(int x, int y, touchType ttype, int touchID);
+    
+    virtual void addHandler(UICallbackFunction handlerFunction, int paramIDX, int paramIDY) // virtual?
+    {
+        cout << "handler added to XYUIElement " << endl;
+        callback = handlerFunction;
+        myParamIDX = paramIDX;
+        myParamIDY = paramIDY;
+    };
+
+    
+private:
+    void drawIndicator();
+    void drawHintIndicator();
+    float maxVal;
+    float minVal;
+    int myParamIDX;
+    int myParamIDY;
+    float hintValuex;
+    float hintValuey;
+    bool hintShowing;
+    string labelNamex;
+    string labelNamey;
+};
+
+#endif /* defined(__tweakathlon__ButtronXY__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/ButtronXY.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,132 @@
+//
+//  ButtronXY.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 25/06/2013.
+//
+//
+
+#include "ButtronXY.h"
+
+ButtronXY::ButtronXY(float ax,
+                             float ay,
+                             float awidth, // width same as height
+                             float athickness,
+                             float aradius,
+                             ofColor aforegroundHi,
+                             ofColor abackgroundHi,
+                             ofColor aforegroundLo,
+                             ofColor abackgroundLo) :
+Buttron(ax,ay,awidth,awidth,athickness,aradius,aforegroundHi,abackgroundHi,aforegroundLo,abackgroundLo)
+
+{
+    
+    cout << "ButtronXY constructor\n";
+    init();
+}
+
+ButtronXY::ButtronXY(float ax,
+          float ay,
+          const UIProps& props) :
+Buttron(ax,ay,props.XYsize ,props.XYsize,props)
+{
+    cout << "ButtronXY constructor\n";
+    init();
+};
+void ButtronXY::init(){
+    xvalue = 0.6;
+    yvalue = 0.7;
+    minVal = 0.;
+    maxVal = 127.;
+    myType = XYPAD;
+    labelNamex = "xxx";
+    labelNamey = "yyy";
+}
+//---------------------------------------------------------------------
+void ButtronXY::drawIndicator(){
+    if(hintShowing) drawHintIndicator();
+    
+    if(on){
+        ofSetColor(foregroundHi);
+    }else{
+        ofSetColor(foregroundLo);
+        
+    }
+    if(inactive){
+        ofSetColor(fgInactive);
+    }
+    
+    // circle and cross hairs
+    ofFill();
+
+    double left = x + thickness + radius;
+    double top = y + radius + thickness;
+    double activeWidth = width - 2*(radius + thickness);
+    double cx = left + xvalue*activeWidth;
+    double cy = top + (1-yvalue)*activeWidth;
+    
+    ofLine(cx,y,cx,y+height);
+    ofLine(x, cy, x+ width, cy);
+    
+    
+    ofEllipse(cx,cy , 2*radius,2*radius);
+
+    
+}
+//---------------------------------------------------------------------
+void ButtronXY::drawHintIndicator(){
+    double left = x + thickness + radius;
+    double top = y + radius + thickness;
+    double activeWidth = width - 2*(radius + thickness);
+
+    // loc = y + hthick +  (1 - hintValue)*(height-3*hthick);
+    ofSetColor(255,255,255);
+    float hthick = 1;
+    double locx = left + hintValuex*activeWidth;
+    double locy = top + (1 - hintValuey)*activeWidth;
+    ofEllipse(locx,locy, hthick,hthick);
+    
+    // draw target dart board thingy
+    ofNoFill();
+    ofSetLineWidth(2);
+    // yellow red blue
+    ofSetColor(255,255,0,166);
+    
+    float rband = activeWidth*TARGET_SCORE_CC_BAND*sqrt(2.0)/127.;
+    ofCircle(locx, locy, rband);
+    ofSetColor(255,0,0,166);
+    ofCircle(locx, locy, rband*2);
+    ofSetColor(45,45,255,166);
+    ofCircle(locx, locy, rband*3);
+    ofSetColor(0,255,0,166);
+    ofCircle(locx, locy, rband*4); // within 20 cc vals?
+    ofFill();
+    
+}
+//---------------------------------------------------------------------
+
+
+bool ButtronXY::handleMyTouch(int tx, int ty, touchType ttype, int touchID){
+
+    double lx = tx - x - thickness - radius;
+    double ly = ty - y - thickness - radius;
+    
+    double propx,propy;
+    propx = lx/(width - 2 * (thickness + radius));
+    propy = 1 - ly/(height - 2 * (thickness + radius));
+    if(propx > 1.) propx = 1.;
+    if(propx < 0.) propx = 0.;
+    if(propy > 1.) propy = 1.;
+    if(propy < 0.) propy = 0.;
+    //cout << "propx: " << propx << endl;
+    setValue(propx,propy);
+    
+    int scaleValx = int((maxVal - minVal)*propx + minVal);
+    int scaleValy = int((maxVal - minVal)*propy + minVal);
+
+    if(callback) callback(myParamIDX,scaleValx);
+    if(callback) callback(myParamIDY,scaleValy);
+    return true;
+}
+
+//---------------------------------------------------------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/CountdownText.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,69 @@
+//
+//  CountdownText.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/03/2014.
+//
+//
+
+#ifndef __tweakathlon__CountdownText__
+#define __tweakathlon__CountdownText__
+
+#include <iostream>
+
+#include "ofMain.h"
+#include "UIElement.h"
+#include "timeController.h"
+#include "boost/function.hpp"
+#include "boost/bind.hpp"
+// actuall a countdown box
+extern TimeController timeController;
+class CountdownText : public UIElement{
+public:
+    
+    CountdownText(string text, int x, int y,int w,int h, const UIProps& props);
+    void draw();
+    
+    ofColor foregroundHi;
+    ofColor backgroundHi;
+    ofColor foregroundLo;
+    ofColor backgroundLo;
+    
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        return false;
+    }
+    
+    void showAndStart(int sec){
+        show();
+        stringstream s;
+        s << sec;
+        numSecondsText = s.str();
+        t = sec;
+        timeController.scheduleEvent(tcb, 1000);
+    };
+    
+    void secPassed(){
+        t--;
+        if(t <= 0){
+            //finish
+            numSecondsText = "0!";
+        }else{
+            stringstream ts;
+            ts << t;
+            numSecondsText = ts.str();
+            timeController.scheduleEvent(tcb, 1000);
+        }
+    };
+    void setTestTypeString(string s){
+        testTypeString = s;
+    }
+private:
+    int t;
+    TimerCallbackFunction tcb;
+    string testTypeString;
+    string numSecondsText;
+};
+
+
+
+#endif /* defined(__tweakathlon__CountdownText__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/CountdownText.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,41 @@
+//
+//  CountdownText.mm
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/03/2014.
+//
+//
+
+#include "CountdownText.h"
+
+CountdownText::CountdownText(string text, int ax, int ay,int aw,int ah, const UIProps& props):
+UIElement(ax,ay,aw,ah, props)
+
+
+{
+    labelName = text;
+    foregroundHi = props.buttonHi;
+    backgroundHi = props.generalBackground;
+    foregroundLo = props.buttonLo;
+    backgroundLo = props.generalBackground;
+    verdana16 = props.verdana16;
+    bigFont = props.bigFont;
+    tcb = boost::bind(&CountdownText::secPassed, this);
+};
+
+//------------------------------------------------------------------
+void CountdownText::draw(){
+    if (hidden) return;
+    UIElement::draw(); // should do background?
+    ofSetColor(foregroundHi);
+    
+    verdana16.drawString(testTypeString, x, y + 8);
+    
+    
+    verdana16.drawString("STARTING IN...", x, y + 108);
+    bigFont.drawString(numSecondsText, x, y + 160);
+    
+    
+    //ofRect(x,y,width,height);
+}
+//------------------------------------------------------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/TextPanel.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,41 @@
+
+#ifndef __tweakathlon__TextPanel__
+#define __tweakathlon__TextPanel__
+
+#include <iostream>
+#include "ofMain.h"
+#include "UIElement.h"
+#include "boost/function.hpp"
+#include "boost/bind.hpp"
+
+class TextPanel : public UIElement{
+public:
+    
+    TextPanel(string text, int x, int y,int w,int h, const UIProps& props);
+    void draw();
+    
+    void setText(string at){
+        theText = at;
+    };
+    void setColor(ofColor col){
+        foregroundHi = col;
+    }
+    void setFontSize(FontSize f){
+        fontSize = f;
+    }
+    ofColor foregroundHi;
+    ofColor backgroundHi;
+    ofColor foregroundLo;
+    ofColor backgroundLo;
+    
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        return false;
+    }
+
+private:
+    string theText;
+    bool transparent;
+    FontSize fontSize;
+};
+
+#endif /* defined(__tweakathlon__TextPanel__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/TextPanel.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,43 @@
+//
+//  TextPanel.mm
+//  tweakathlon
+//
+//  Created by Robert Tubb on 05/03/2014.
+//
+//
+
+#include "TextPanel.h"
+
+TextPanel::TextPanel(string text, int ax, int ay,int aw,int ah, const UIProps& props):
+UIElement(ax,ay,aw,ah, props)
+
+
+{
+    labelName = text;
+    foregroundHi = props.buttonHi;
+    backgroundHi = props.generalBackground;
+    foregroundLo = props.buttonLo;
+    backgroundLo = props.generalBackground;
+    verdana16 = props.verdana16;
+    bigFont = props.bigFont;
+    smallFont = props.smallFont;
+    transparent = true;
+};
+
+//------------------------------------------------------------------
+void TextPanel::draw(){
+    if (hidden) return;
+    if(!transparent) UIElement::draw(); // should do background
+    ofSetColor(foregroundHi);
+    
+    // TODO check for fitting inside??
+    if(fontSize == SMALLFONT){
+        smallFont.drawString(theText, x, y + 8);
+    }else if(fontSize == LARGEFONT){
+        bigFont.drawString(theText, x, y + 8);
+    }else{
+        verdana16.drawString(theText, x, y + 8);
+    }
+    
+    //ofRect(x,y,width,height);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIElement.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,151 @@
+//
+//  UIElement.h
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+// literally just an area of the screen that is a ui element
+
+#ifndef __emptyExample__UIElement__
+#define __emptyExample__UIElement__
+#include "ofMain.h"
+#include "globalVariables.h"
+#include <iostream>
+#include <string>
+#include "boost/function.hpp"
+#include "UIProperties.h"
+
+typedef boost::function<void(int, int)> UICallbackFunction;
+
+class MessageOrganiser;
+
+class UIElement{
+public:
+
+    
+    UICallbackFunction callback;
+    
+    UIElement();
+    virtual ~UIElement(){};
+    // recommended
+    UIElement(float ax,
+              float ay,
+              float awidth,
+              float aheight,
+              const UIProps& props);
+              
+    UIElement(float ax,
+              float ay,
+              float awidth,
+              float aheight,
+              ofColor bg);
+
+    virtual void setLabel(string label){
+        labelName = label;
+    }
+    virtual void draw();
+    void hide(){
+        hidden = true;
+        on = false;
+        
+    };
+    void show(){
+        hidden = false;
+        on = true;
+    
+    };
+    bool touch(int x, int y, touchType ttype, int touchID);
+    
+    virtual void addHandler(UICallbackFunction handlerFunction, int paramID) // virtual?
+    {
+        cout << "handler added to UIElement " << endl;
+        callback = handlerFunction;
+        myParamID = paramID;
+    };
+    
+    virtual void setValue(float value){
+        cout << "not valid to set value on this?" << endl;
+    };
+    virtual void setHintValue(float value){
+        cout << "not valid to set value on this?" << endl;
+    };
+    virtual void showHint(bool value){
+        cout << "not valid to set value on this?" << endl;
+    };
+    virtual void setHintColor(ofColor c){
+        cout << "not valid to set value on this?" << endl;
+    };
+    controllerType getType() const {
+        return myType;
+    }
+    float getWidth() const {return width;};
+    virtual void setHighlight(bool hion){
+        // ?
+        on = hion;
+    };
+    void setActive(bool isActive){
+        inactive = !isActive; // thats logic right?
+    }
+    void setX(float ax){
+        x = ax;
+    };
+    void setY(float ay){
+        y = ay;
+    };
+protected:
+    
+    float x;
+    float y;
+    float width;
+    float height;
+    bool on;
+    int myParamID;
+    list<int> myTouchIDs;
+    
+    ofColor background;
+    
+    string labelName;
+    ofTrueTypeFont verdana16;
+    ofTrueTypeFont bigFont;
+    ofTrueTypeFont smallFont;
+    controllerType myType;
+    
+    bool hidden; // don't draw dont touch
+    bool inactive;  // dont touch, draw dimmed
+
+    void init();
+    
+    bool isExistingTouchID(int touchID){
+        // is id in list
+        std::list<int>::iterator findIter = std::find(myTouchIDs.begin(), myTouchIDs.end(), touchID);
+        if (findIter == myTouchIDs.end()){
+            return false;
+        }else{
+            return true;
+        }
+    };
+
+    void addTouchID(int touchID){
+        //list<int>::iterator findIter = std::find(myTouchIDs.begin(), myTouchIDs.end(), touchID);
+        //if(findIter == myTouchIDs.end()){ // checks for duplicates
+            myTouchIDs.insert(myTouchIDs.begin(), touchID);
+        //}
+    };
+    void removeTouchID(int touchID){
+        list<int>::iterator findIter = std::find(myTouchIDs.begin(), myTouchIDs.end(), touchID);
+        if(findIter != myTouchIDs.end()){
+            myTouchIDs.erase(findIter);
+        }
+    };
+    static float sumWidth(float total, UIElement* element){
+        return total + element->getWidth();
+    }
+    bool isMyTouch(int x, int y, touchType ttype, int touchID);
+    bool touchIsInMyArea(int tx, int ty);
+    virtual bool handleMyTouch(int x, int y, touchType ttype, int touchID) = 0; // subclass handles it
+
+    bool isCoordInMyRegion(double x, double y); // not used
+    
+    
+};
+#endif /* defined(__emptyExample__UIElement__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIElement.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,147 @@
+//
+//  UIElement.cpp
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#include "UIElement.h"
+//----------------------------------------------------------------------
+UIElement::UIElement(){
+    //
+    //cout << " UIElement default constructur BAD !!!\n";
+    init();
+}
+//----------------------------------------------------------------------
+UIElement::UIElement(float ax,
+                     float ay,
+                     float awidth,
+                     float aheight,
+                     const UIProps& props) :
+x(ax),
+y(ay),
+width(awidth),
+height(aheight),
+background(props.generalBackground)
+{
+    //cout << " UIElement constructur with defs \n";
+    init();
+    verdana16 = props.verdana16;
+    bigFont = props.bigFont;
+    
+}
+//----------------------------------------------------------------------
+UIElement::UIElement(float ax,
+                     float ay,
+                     float awidth,
+                     float aheight,
+                     ofColor bg) :
+x(ax),
+y(ay),
+width(awidth),
+height(aheight),
+background(bg)
+{
+    init();
+
+}
+//----------------------------------------------------------------------
+void UIElement::init(){
+
+    
+    hidden = false;
+    inactive = false;
+}
+//----------------------------------------------------------------------
+void UIElement::draw(){
+    if(hidden) return;
+    //cout<<"element draw\n";
+    ofSetColor(background);
+    ofRect(x,y,width,height);
+    
+    
+};
+//----------------------------------------------------------------------
+bool UIElement::touch(int tx, int ty, touchType ttype, int touchID){
+    if(isMyTouch(tx,ty,ttype,touchID)){
+        handleMyTouch(tx, ty, ttype,touchID);
+        return true;
+    }else{
+        return false;
+    }
+}
+//----------------------------------------------------------------------
+// called first from all subclasses
+bool UIElement::isMyTouch(int tx, int ty, touchType ttype, int touchID){
+    if(hidden || inactive) return false;
+
+    if(ttype == TOUCH_DOWN){
+        if (touchIsInMyArea(tx, ty)){
+            if (!isExistingTouchID(touchID)){
+                //cout << "Touchdown in area, grabbing focus " << labelName << " mytouchID: " << myTouchID << " finger ID: " << touchID << endl;
+                addTouchID(touchID);
+                return true;
+
+            }else{
+                //shouldn't happen?
+                return true;
+            }
+
+        }else{
+            //cout << "Touchdown outside area, ignoring " << labelName << " mytouchID: " << myTouchID << " finger ID: " << touchID << endl;
+            return false;
+
+        }
+    }
+    if(ttype == TOUCH_UP){
+        if (isExistingTouchID(touchID)){
+            //cout << "Touch Up for my ID, handling " << labelName << " mytouchID: " << myTouchID << " finger ID: " << touchID << endl;
+            //myTouchID = -1;
+            removeTouchID(touchID);
+            return true;
+        }else{
+            //cout << "Touch Up NOT my  ID, ignoring " << labelName << " mytouchID: " << myTouchID << " finger ID: " << touchID << endl;
+            return false;
+        }
+    }
+    
+    if(ttype == TOUCH_MOVED){
+        if(isExistingTouchID(touchID)){
+            //cout << "Touch moved for my ID, handling " << labelName << " mytouchID: " << myTouchID << " finger ID: " << touchID << endl;
+            return true;
+        }else{
+            //cout << "Touch moved NOT my ID, ignore " << labelName << " mytouchID: " << myTouchID << " finger ID: " << touchID << endl;
+            return false;
+        }
+    }
+    
+    cout << "UNHANDLED SITUATION!" << labelName << endl;
+    return false;
+
+}
+
+//----------------------------------------------------------------------
+bool UIElement::touchIsInMyArea(int tx, int ty){
+    
+    // work out relative coords
+    double relx = tx - x;
+    double rely = ty - y;
+    return !(relx < 0 || relx > width || rely < 0 || rely > height);
+}
+//----------------------------------------------------------------------
+bool UIElement::isCoordInMyRegion(double ax, double ay){
+    if(hidden) return false;
+    
+    if( (ax > x && ax < x+width) && (ay > y && ay < y+height)){
+        return true;
+    }else{
+        return false;
+    }
+  
+}
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
+//----------------------------------------------------------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIElementContainer.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,107 @@
+//
+//  UIElementContainer.h
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+
+// a meta button, with border. 
+
+#ifndef __emptyExample__UIElementContainer__
+#define __emptyExample__UIElementContainer__
+
+#include <iostream>
+#include "globalVariables.h"
+#include "ofMain.h"
+#include "UIElement.h"
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+#include "timeController.h"
+// is a UI "panel" containing sub elements
+// helps control the focus of the touch event
+
+
+extern TimeController timeController;
+
+class UIElementContainer: public UIElement{
+public:
+    UIProps myProps;
+    vector<UIElement *> subElements;
+    UIElementContainer();
+    ~UIElementContainer(){
+        removeAllSubelements();
+    };
+    UIElementContainer(float ax,
+              float ay,
+              float awidth,
+              float aheight,
+              const UIProps& props); // constructor 1 : we add stuff later
+
+    void addElement(UIElement *elm){
+        subElements.push_back(elm);
+        
+    };
+    void removeAllSubelements();
+    
+    int getNumberOfControls();
+    UIElement* getElement(int idx){
+        if (idx < subElements.size()){
+            return subElements[idx];
+        }else{
+            cout << "ERROR ERROR: index too big for subelemens" << endl;
+        }
+        
+    }
+    void showBorder(bool s){
+        if(s){
+            cthickness = 1;
+        
+        }
+    }
+    virtual void draw();
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        vector<UIElement *>::iterator UIitr;
+        for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+            (*UIitr)->touch(x,y,ttype,touchID);
+        }
+        return true;
+    }
+
+    void setActive(bool isActive){
+        vector<UIElement *>::iterator UIitr;
+        for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+            (*UIitr)->setActive(isActive);
+        }
+    }
+
+    void autoArrangeRow(){
+        // goes thru subelements and sets x and y pos to something sensible
+        
+        // add up all element widths
+        float sum = accumulate(subElements.begin(), subElements.end(), 0.0, &UIElement::sumWidth);
+        
+        float spaceLeft = width - sum;
+        
+        float spac = spaceLeft/(getNumberOfControls()+1);
+        
+        if (spac <= 0){
+            cout << "ERROR: not enough space for controls" << endl;
+            
+        }
+        float pos = spac;
+        vector<UIElement *>::iterator ei;
+        for(ei = subElements.begin(); ei < subElements.end(); ei++){
+            (*ei)->setX(pos);
+            pos = pos + (*ei)->getWidth() + spac;
+        }
+        // TODO y set to centred
+    }
+private:
+    void drawBorder();
+    double cthickness;
+    bool flashing;
+};
+
+#endif /* defined(__emptyExample__UIElementContainer__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIElementContainer.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,73 @@
+    //
+//  UIElementContainer.cpp
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#include "UIElementContainer.h"
+#include "ButtronXY.h"
+#include "ButtronSlider.h"
+
+//-----------------------------------------------------------------------------
+UIElementContainer::UIElementContainer(float ax,
+                                       float ay,
+                                       float awidth,
+                                       float aheight,
+                                       const UIProps& aprops) :
+UIElement(ax,ay,awidth,aheight,aprops.generalBackground)
+{
+    cout << "UIElementContainer contructor\n";
+    
+    myProps = aprops;
+    cthickness = 0.;
+
+}
+
+//-----------------------------------------------------------------------------
+int UIElementContainer::getNumberOfControls(){
+    return subElements.size();
+}
+
+
+//-----------------------------------------------------------------------------
+
+void UIElementContainer::removeAllSubelements(){
+    vector<UIElement *>::iterator UIitr;
+    for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+        delete (*UIitr);
+    }
+    subElements.clear();
+}
+//-------------------------------------------------------------------
+void UIElementContainer::draw(){
+    if(hidden) return;
+    //cout << "DRAWING CONTAINER"<< endl;
+    UIElement::draw();
+    // draw me
+    if(cthickness != 0.){
+        // doh, duplicate code from buttron?
+        drawBorder();
+    }
+    
+    // draw my subelems
+    vector<UIElement *>::iterator UIitr;
+    for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+        (*UIitr)->draw();
+    }
+};
+//-------------------------------------------------------------------
+void UIElementContainer::drawBorder(){
+    ofSetLineWidth(cthickness);
+    ofSetColor(myProps.borderColor);
+    // top
+    ofLine(x,y,x+width,y);
+    // left
+    ofLine(x,y,x,y+height);
+    //right
+    ofLine(x+width-cthickness,y,x+width-cthickness,y+height);
+    // bottom
+    ofLine(x-cthickness,y+height,x+width-cthickness,y+height);
+}
+//-------------------------------------------------------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIGrid.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,32 @@
+//
+//  UIGrid.h
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#ifndef __emptyExample__UIGrid__
+#define __emptyExample__UIGrid__
+#include "ofMain.h"
+#include "Buttron.h" // no
+#include "UIElement.h"
+#include "UIElementContainer.h"
+#include <iostream>
+
+template<class T>
+class UIGrid: public UIElementContainer{
+public:
+    int rows;
+    int columns;
+    int spacing;
+    // too fuckin long
+    UIGrid(int ax,int ay, int awidth, int aheight, int numRows, int numColumns, int spacing,ofColor hi, ofColor lo, ofColor bg);
+    vector<vector<UIElement *> > subElementsByCoordinate;
+    
+    // draw and touch all handled by UIElementContainer...
+    
+    void print();
+    
+};
+#endif /* defined(__emptyExample__UIGrid__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIGrid.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,43 @@
+//
+//  UIGrid.cpp
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#include "UIGrid.h"
+
+
+
+template<class T> void UIGrid<T>::print(){
+    cout << "uh \n";
+}
+
+template<class T> UIGrid<T>::UIGrid(int ax,int ay, int awidth, int aheight, int numColumns,int numRows,  int spacing,ofColor hi, ofColor lo, ofColor bg)
+{
+    
+    // grid of what ?
+    double cw = width/(double)numColumns;
+    double ch = height/(double)numRows;
+    
+    double eWidth = cw - spacing;
+    double eHeight = ch - spacing;
+    double ex,ey;
+    double radius = (eWidth < eHeight ? eWidth : eHeight)/6.0;
+    double thickness = radius;
+    for(int i=0; i< numColumns; i++){
+        ex = x + i*cw + spacing/2.0;
+        for(int j=0; j<numRows; j++){
+            // make buttons
+            
+            ey = y + j*ch + spacing/2.0;
+            T *butt = new T(ex,ey,eWidth,eHeight,thickness,radius,hi,bg,lo,bg);
+        
+            
+            subElements.push_back(butt);
+        }
+    }
+    
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/UIProperties.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,86 @@
+#pragma once
+#include <iostream>
+#include "ofMain.h"
+// this is all the default global colors and sizes for the UI, passed into uielement conststrutor
+
+struct UIProps {
+    
+    int buttonWidth;
+    int buttonHeight;
+    
+    int borderThickness;
+    int cornerRadius;
+    
+    int sliderPanelWidth;
+    int sliderPanelHeight;
+    int spacerSize;
+    int XYsize;
+    
+    int sliderWidth;
+    int sliderHeight;
+    float sliderMinVal;
+    float sliderMaxVal;
+    ofColor buttonLo;
+    ofColor buttonHi;
+    
+    ofColor inactiveGreyedOut;
+    
+    ofColor sliderMultiActive;
+    
+    ofColor sliderSimulInactive;
+    ofColor sliderSimulActive;
+    
+    ofColor generalBackground;
+    ofColor borderColor;
+    ofColor hintColor;
+    
+    ofTrueTypeFont verdana16;
+    ofTrueTypeFont bigFont;
+    ofTrueTypeFont smallFont;
+    
+    UIProps(){
+        
+        // LOAD FONT SLOW
+        verdana16.loadFont("verdana.ttf", 14, true, true);
+        verdana16.setLineHeight(18.0f);
+        verdana16.setLetterSpacing(1.037);
+        
+        bigFont.loadFont("verdana.ttf", 28, true, true);
+        bigFont.setLineHeight(22.0f);
+        bigFont.setLetterSpacing(1.037);
+        
+        smallFont.loadFont("verdana.ttf", 10, true, true);
+        smallFont.setLineHeight(11.0f);
+        smallFont.setLetterSpacing(1.037);
+        
+        buttonWidth = 150;
+        buttonHeight = 60;
+        borderThickness = 5;
+        cornerRadius = 7;
+        
+        sliderPanelWidth = ofGetWidth();
+        sliderPanelHeight = 500;
+        spacerSize = 40;
+        XYsize = sliderPanelHeight - spacerSize*2;
+        
+        sliderWidth = XYsize/4;
+        sliderHeight = XYsize;
+        sliderMinVal = 0.   ;
+        sliderMaxVal = 127.;
+        
+        borderColor = ofColor(123,200,180,180);
+        hintColor = ofColor(255,0,0,255);
+        
+        buttonLo = ofColor(123,200,180,255);
+        buttonHi = ofColor(150,235,200,255);
+        
+        inactiveGreyedOut = ofColor(78,78,78,255);
+        
+        sliderMultiActive = ofColor(255,255,0,255);
+        
+        sliderSimulInactive = ofColor(200,0,0,255);
+        sliderSimulActive = ofColor(0,255,0,255);
+        
+        generalBackground = ofColor(23,23,23,255);
+    };
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/buttonPanel.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,50 @@
+//
+//  buttonPanel.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 11/02/2014.
+//
+//
+
+#ifndef __tweakathlon__buttonPanel__
+#define __tweakathlon__buttonPanel__
+
+#include <iostream>
+#include <iostream>
+#include "UIElementContainer.h"
+#include <iostream>
+#include "globalVariables.h"
+#include "ofMain.h"
+#include "UIElement.h"
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+#include "timeController.h"
+#include "ButtronSlider.h"
+#include "ButtronXY.h"
+#include "Buttron.h"
+// a row of buttons, spaced out nicely
+
+class ButtonPanel : public UIElementContainer{
+    
+public:
+    ButtonPanel(float ax,
+                float ay,
+                float awidth,
+                float aheight,
+                const UIProps& aprops,
+                vector<controllerType> elemList);
+    ButtonPanel(float ax,
+                float ay,
+                float awidth,
+                float aheight,
+                const UIProps& aprops);
+    vector<UIElement*>  generateControls(vector<controllerType> elemList);
+    
+    void addButton(Buttron* aButton){
+        subElements.push_back(aButton);
+        autoArrangeRow();
+    }
+
+};
+
+#endif /* defined(__tweakathlon__buttonPanel__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/buttonPanel.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,58 @@
+//
+//  buttonPanel.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 11/02/2014.
+//
+//
+
+#include "buttonPanel.h"
+ButtonPanel::ButtonPanel(float ax,
+                         float ay,
+                         float awidth,
+                         float aheight,
+                         const UIProps& aprops,
+                         vector<controllerType> elemList) :
+UIElementContainer(ax,ay,awidth,aheight,aprops)
+{
+    cout << "ButtonPanel auto layout contructor\n";
+    
+    generateControls(elemList);
+    autoArrangeRow();
+}
+//---------------------------------------------------
+ButtonPanel::ButtonPanel(float ax,
+                         float ay,
+                         float awidth,
+                         float aheight,
+                         const UIProps& aprops) :
+UIElementContainer(ax,ay,awidth,aheight,aprops)
+{
+    cout << "ButtonPanel - ctrls added later constructor\n";
+
+}
+//---------------------------------------------------
+vector<UIElement*> ButtonPanel::generateControls(vector<controllerType> elemList){
+    removeAllSubelements();
+    vector<controllerType>::iterator i;
+    
+    // 10 cm is 520 pixels
+    
+    // calc positions
+    int top  = y + myProps.spacerSize;
+    
+    int n=0;
+    for(i=elemList.begin(); i<elemList.end();i++){
+        if(*i == BUTTON){
+            // add a slider
+            Buttron * butt = new Buttron(0 , top , myProps.buttonWidth, myProps.buttonHeight,myProps);
+            butt->setLabel("unassigned");
+            subElements.push_back(butt);
+            n++;
+
+        }else{
+            cout << "ERROR: button panel only handles buttons" << endl;
+        }
+    }
+    return subElements;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/sliderPanel.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,81 @@
+//
+//  sliderPanel.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 11/02/2014.
+//
+//
+
+#ifndef __tweakathlon__sliderPanel__
+#define __tweakathlon__sliderPanel__
+
+#include <iostream>
+#include "UIElementContainer.h"
+#include <iostream>
+#include "globalVariables.h"
+#include "ofMain.h"
+#include "UIElement.h"
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+#include "timeController.h"
+#include "ButtronSlider.h"
+#include "ButtronXY.h"
+#include "3Dbox.h"
+#include "3DboxGL.h"
+// panel with sliders and xy pads
+class SliderPanel : public UIElementContainer{
+    
+public:
+    SliderPanel(float ax,
+                float ay,
+                float awidth,
+                float aheight,
+                const UIProps& aprops,
+                vector<controllerType> elemList);
+    //------------------------
+    void showHint(bool value){
+        vector<UIElement *>::iterator UIitr;
+        for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+            (*UIitr)->showHint(value);
+        }
+    }
+    //
+    void setHintColor(ofColor c){
+        vector<UIElement *>::iterator UIitr;
+        for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+            (*UIitr)->setHintColor(c);
+        }
+    }
+    //------------------------
+    void flash(){
+        // turn hilight on and off
+        if (!flashing){
+            vector<UIElement *>::iterator UIitr;
+            for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+                (*UIitr)->setHighlight(true);
+            }
+            // set up timer
+            TimerCallbackFunction tcb;
+            tcb = boost::bind(&SliderPanel::flash, this);
+            timeController.scheduleEvent(tcb, 250);
+            flashing = true;
+        }else{
+            vector<UIElement *>::iterator UIitr;
+            for(UIitr = subElements.begin(); UIitr < subElements.end(); UIitr++){
+                (*UIitr)->setHighlight(false);
+            }
+            flashing = false;
+        }
+        
+    }
+    //------------------------
+    vector<UIElement*> generateControls(vector<controllerType> elemList, controlPanelType panelType);
+    //------------------------
+    
+    // TODO override touch thing to make revisitable
+private:
+    bool flashing;
+    controlPanelType panelType;
+};
+
+#endif /* defined(__tweakathlon__sliderPanel__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/sliderPanel.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,99 @@
+//
+//  sliderPanel.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 11/02/2014.
+//
+//
+
+#include "sliderPanel.h"
+
+//-----------------------------------------------------------------------------
+SliderPanel::SliderPanel(float ax,
+                         float ay,
+                         float awidth,
+                         float aheight,
+                         const UIProps& aprops,
+                         vector<controllerType> elemList) :
+UIElementContainer(ax,ay,awidth,aheight,aprops)
+{
+    cout << "SliderPanel auto layout contructor\n";
+
+    // generateControls(elemList);// called from messageorganiser
+}
+
+// NOT GENERIC
+//-----------------------------------------------------------------------------
+vector<UIElement*> SliderPanel::generateControls(vector<controllerType> elemList, controlPanelType panelType){
+    removeAllSubelements();
+    vector<controllerType>::iterator i;
+    
+    // 10 cm is 520 pixels
+    
+    // calc positions
+    int top  = y + myProps.spacerSize;
+    
+    float pixPerElem = width/(float)elemList.size();
+    if (pixPerElem < myProps.sliderWidth ){
+        cout << "error not enough room for sliders" << endl;
+    }
+    
+    int n=0;
+    for(i=elemList.begin(); i<elemList.end();i++){
+        if(*i == SLIDER){
+            // add a slider
+            float c = (n + 0.5) * pixPerElem;
+            float l = c - myProps.sliderWidth/2;
+            if(n==1){
+                cout << "centre " << c << endl;
+                cout << l << endl;
+            }
+            
+            ButtronSlider * revslider = new ButtronSlider(l , top , myProps.sliderWidth, myProps.sliderHeight,FILL, myProps);
+            revslider->setLabel("unassigned");
+            subElements.push_back(revslider);
+            revslider->showHint(false);
+            // grey out all but first
+            if(panelType == SEQUENTIAL && i != elemList.begin()){
+                revslider->setActive(false);
+            }
+            
+            n++;
+            
+        }else if(*i == XYPAD){
+            // add a xy
+            float c = (n + 0.5) * pixPerElem;
+            float left = c - myProps.XYsize/2;
+            ButtronXY * xyp = new ButtronXY(left , top , myProps);
+            xyp->setLabel("unassigned","unassigned");
+            xyp->showHint(false);
+            subElements.push_back(xyp);
+            n++;
+        }else if(*i == LEAP3D){
+            // add a threed box
+            float c = x+width*0.5;
+            float left = c - myProps.XYsize;
+            
+            //Leap3DBox * l3d = new Leap3DBox(left , top+50 , myProps.XYsize*0.75,myProps.XYsize*0.75,150,50, myProps);
+
+            Leap3DBoxGL * l3d = new Leap3DBoxGL(left , top+50 , myProps.XYsize*0.75,myProps.XYsize*0.75,150,50, myProps);
+            
+
+            
+            subElements.push_back(l3d);
+            n++;
+        
+        }else{
+            cout << "ERROR: slider panel only handles xy pads and sliders" << endl;
+        }
+        
+
+    }
+    
+    autoArrangeRow(); // will set positions
+    
+
+
+    return subElements;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/targetSymbol.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,84 @@
+//
+//  targetSymbol.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 11/02/2014.
+//
+//
+
+#ifndef __tweakathlon__targetSymbol__
+#define __tweakathlon__targetSymbol__
+
+#include <iostream>
+#include "UIElement.h"
+#include "timeController.h"
+extern TimeController timeController;
+class TargetSymbol : public UIElement {
+public:
+    
+    TargetSymbol(int ax, int ay,int aw, const UIProps& props):
+    UIElement(ax,ay,aw,aw, props)
+    {
+        foregroundHi = props.buttonHi;
+        backgroundHi = props.generalBackground;
+        foregroundLo = props.inactiveGreyedOut; // can't be touched
+        backgroundLo = props.generalBackground;
+        flashing = false;
+        on = false;
+    };
+    
+    void draw(){
+        if(hidden)return;
+        //UIElement::draw(); // don't do background
+        ofColor fg,bg;
+        
+        if(on){
+            fg = foregroundHi;
+            bg = backgroundHi;
+        }else{
+            fg = foregroundLo;
+            bg = backgroundLo;
+        }
+        ofSetColor(fg);
+
+        ofEllipse(x,y,width,height);
+        
+        ofSetColor(bg);
+        ofEllipse(x,y,width*0.66,height*0.66);
+        
+        ofSetColor(fg);
+        ofEllipse(x,y,width*0.33,height*0.33);
+        
+    };
+    
+    void flash(){
+        // turn hilight on and off
+        if (!flashing){
+            setHighlight(true);
+            
+            // set up timer
+            TimerCallbackFunction tcb;
+            tcb = boost::bind(&TargetSymbol::flash, this);
+            timeController.scheduleEvent(tcb, int(ALTERNATION_SPEED/4));
+            flashing = true;
+        }else{
+            setHighlight(false);
+            
+            flashing = false;
+        }
+        
+    }
+    
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        return false; // or?
+    }
+    
+private:
+    ofColor foregroundHi;
+    ofColor backgroundHi;
+    ofColor foregroundLo;
+    ofColor backgroundLo;
+    ofColor fgInactive;
+    bool flashing;
+};
+#endif /* defined(__tweakathlon__targetSymbol__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/targetSymbol.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,9 @@
+//
+//  targetSymbol.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 11/02/2014.
+//
+//
+
+#include "targetSymbol.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/textLabel.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,66 @@
+//
+//  textLabel.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/02/2014.
+//
+//
+
+#ifndef __tweakathlon__textLabel__
+#define __tweakathlon__textLabel__
+
+#include <iostream>
+#include "ofMain.h"
+#include "UIElement.h"
+#include "timeController.h"
+#include "boost/function.hpp"
+#include "boost/bind.hpp"
+// actuall a countdown box
+extern TimeController timeController;
+class TextLabel : public UIElement{
+public:
+
+    TextLabel(string text, int x, int y,int w,int h, const UIProps& props);
+    void draw();
+    
+    void setText(string at){
+        labelName = at;
+    };
+    
+    ofColor foregroundHi;
+    ofColor backgroundHi;
+    ofColor foregroundLo;
+    ofColor backgroundLo;
+    
+    bool handleMyTouch(int x, int y, touchType ttype, int touchID){
+        return false;
+    }
+    
+    void showAndStart(int sec){
+        show();
+        stringstream s;
+        s << sec;
+        labelName = s.str();
+        t = sec;
+        timeController.scheduleEvent(tcb, 1000);
+    };
+        
+    void secPassed(){
+        t--;
+        if(t <= 0){
+            //finish
+            labelName = "!";
+        }else{
+            stringstream ts;
+            ts << t;
+            labelName = ts.str();
+            timeController.scheduleEvent(tcb, 1000);
+        }
+    };
+private:
+    int t;
+    TimerCallbackFunction tcb;
+    
+};
+
+#endif /* defined(__tweakathlon__textLabel__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UI code/textLabel.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,37 @@
+//
+//  textLabel.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/02/2014.
+//
+//
+
+#include "textLabel.h"
+
+TextLabel::TextLabel(string text, int ax, int ay,int aw,int ah, const UIProps& props):
+    UIElement(ax,ay,aw,ah, props)
+
+
+{
+    labelName = text;
+    foregroundHi = props.buttonHi;
+    backgroundHi = props.generalBackground;
+    foregroundLo = props.buttonLo;
+    backgroundLo = props.generalBackground;
+    verdana16 = props.verdana16;
+    bigFont = props.bigFont;
+    tcb = boost::bind(&TextLabel::secPassed, this);
+};
+
+//------------------------------------------------------------------
+void TextLabel::draw(){
+    if (hidden) return;
+    UIElement::draw(); // should do background
+    ofSetColor(foregroundHi);
+    verdana16.drawString("NEXT TEST IN...", x, y + 8);
+    bigFont.drawString(labelName, x, y + 60);
+    
+    
+    //ofRect(x,y,width,height);
+}
+//------------------------------------------------------------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UsernameAlertViewController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,19 @@
+//
+//  iViewController.h
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 07/01/2013.
+//
+//
+
+#import <Foundation/Foundation.h>
+
+@interface UsernameAlertViewController : NSObject <UIAlertViewDelegate, UITextFieldDelegate>
+
+@property (strong,nonatomic) UIAlertView * alert;
+@property (nonatomic, assign)       id theOFAppRef;
+-(void)showUserNamePrompt;
+-(void)setAppRef:(id)theAppRef;
+
+@end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UsernameAlertViewController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,87 @@
+//
+//  iViewController.m
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 07/01/2013.
+//
+//
+#include "testApp.h"
+#include "eventLogger.h"
+
+#import "usernameAlertViewController.h"
+
+
+extern EventLogger eventLogger;
+
+@implementation UsernameAlertViewController
+
+-(void)showUserNamePrompt{
+
+    
+    self.alert = [[UIAlertView alloc] initWithTitle:@"Hello!"
+                                                     message:@"Please enter your name:"
+                                                    delegate:self
+                                                    cancelButtonTitle:@"Continue"
+                                                    otherButtonTitles:nil];
+    self.alert.alertViewStyle = UIAlertViewStylePlainTextInput;
+    UITextField * alertTextField = [self.alert textFieldAtIndex:0];
+    [alertTextField setDelegate:self];
+    alertTextField.keyboardType = UIKeyboardTypeDefault;
+    alertTextField.placeholder = @"Username";
+    [self.alert show];
+    //[self.alert release];
+
+    
+}
+-(void)setAppRef:(id)theAppRef{
+    self.theOFAppRef = theAppRef;
+}
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
+    
+    NSLog(@"Entered: %@",[[alertView textFieldAtIndex:0] text]);
+    NSString *userName = [[alertView textFieldAtIndex:0] text];
+    if ([userName isEqualToString:@""]){
+        [self showUserNamePrompt];
+        return;
+    }
+    eventLogger.setUsername([userName cStringUsingEncoding:NSASCIIStringEncoding]);
+    
+    // call some start func
+    ((testApp *)self.theOFAppRef)->startTheTests();
+    // rememebr to change return func too!
+
+}
+
+-(BOOL)textFieldShouldReturn:(UITextField *)textField{
+
+    NSLog(@"Entered: %@",[[self.alert textFieldAtIndex:0] text]);
+    NSString *userName = [[self.alert textFieldAtIndex:0] text];
+    if ([userName isEqualToString:@""]){
+        [self showUserNamePrompt];
+        
+    }else{
+        eventLogger.setUsername([userName cStringUsingEncoding:NSASCIIStringEncoding]);
+        ((testApp *)self.theOFAppRef)->startTheTests();
+        
+    }
+    [self.alert dismissWithClickedButtonIndex:self.alert.firstOtherButtonIndex animated:YES];
+    return YES;
+}
+
+- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
+{
+    UITextField *textField = [alertView textFieldAtIndex:0];
+    if ([textField.text length] == 0)
+    {
+        return NO;
+    }
+    return YES;
+}
+
+
+@end
+
+
+// global. again.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/algorithms.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "ofMain.h"
+#include <functional>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eventLogger.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,219 @@
+//
+//  eventLogger.h
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 05/11/2012.
+//
+//
+// This class handle everything to do with loggin user actions,
+// uploading logs to server, and storing locally if not uploaded
+
+#ifndef __oscSenderExample__eventLogger__
+#define __oscSenderExample__eventLogger__
+
+
+#include "ofMain.h"
+#include "ofxiPhone.h"
+#include "2dvector.h"
+#include "ofxiPhoneExtras.h"
+#include <sys/time.h>
+#include <iostream>
+#include <string>
+#include <cstring>
+#include <map>
+#include "2dvector.h"
+#include "json.h"
+#import "ServerComms.h"
+#include "boost/bind.hpp"
+#include "boost/function.hpp"
+#include "Poco/Mutex.h"
+
+#define EVENT_THIN_FACTOR 30
+#define EVENT_LOG_FILENAME "log.json"
+#define UPLOAD_CHUNK_SIZE 1000
+#define APP_CREATION_TIME 0   // ignore this, pointless
+#define PROGRAM_NAME "TWEAKATHLON"
+#define PROGRAM_VERSION 0.2
+
+#define SUPERVISED // this def will save files
+
+
+// can add but don't change ordering - this will invalidate logs
+enum leventType {APP_LOADED,                // 0
+                INTRO_CONSENTED,            // 1
+                APP_EXITED,                 // 2
+                HELP_PRESSED,               // 3
+                QUESTIONNAIRE_COMPLETED,    // 4
+    
+                NEW_TEST,                   // 5
+                // al the set up of the new test
+                TARGET_PARAM_SET,           // 6 setting up the target sound, param id and value
+                CANDIDATE_PARAM_SET,        // 7 setting up the cand sound starting pos, subset of param id and value
+                CANDIDATE_CHANGEABLE_IDX,   // 8 list of changeable indexes
+                CANDIDATE_MAPPING_IDS,      // 9 which kind of control was mapped to which param
+                CONTROL_LIST,               // 10 list of control types
+    
+                TEST_TIMER_STARTED,         // 11 we're off!!
+    
+                CANDIDATE_PARAM_ADJUSTED,   // 12 interactions changing params
+                SUBMIT_PRESSED,             // 13 this is the suer saying they've found it, along with the actual answer
+                DISTANCE_TIME_SCORE,        // 14 list of the results, now we should go back to NEW_TEST
+                COUNTDOWN_INITIATED,        // 15 just in case
+                ALL_TESTS_COMPLETED,               // 16 ?
+                TARGET_PLAYED,              // 17 however this happens it might be good to know when this happens
+                CANDIDATE_PLAYED,           // 18
+                START_THE_TESTS,            // 19 probably superfluous
+                CRAP_TEST,                  // eliminate these coords somehow ???
+                EMPTY_EVENT,
+                SPEED_CHANGED,              // 22 ms between sounds
+    
+};
+
+//---------------------------------------------------------------------------
+
+class lEvent{
+public:
+    // try and make this as compact as possible.
+    leventType eventType;
+    double val1; // x coord, scale if zoom
+    double val2; // y coord, 0 if zoom
+    int sliderID; // xtra int 
+    long long eventTime; // MILLISECONDS since ref date
+    vector<int> eventData; // variable length data int
+    
+    // old sonic zoom style event
+    lEvent(leventType eType, double v1 = 0.0, double v2 = 0.0,int sID = 0){
+        eventType = eType;
+        val1 = v1;
+        val2 = v2;
+        sliderID = sID;
+        
+        double timemsd = [NSDate timeIntervalSinceReferenceDate]; // MILLISECONDS, but with fractional part (
+        eventTime = (unsigned long long)(timemsd*1000) - APP_CREATION_TIME;
+        
+    }
+    
+    // new tweakathlon event
+    lEvent(leventType eType, vector<int> theData){
+        eventType = eType;
+        eventData = theData;
+        
+        double timemsd = [NSDate timeIntervalSinceReferenceDate]; // MILLISECONDS, but with fractional part (
+        eventTime = (unsigned long long)(timemsd*1000) - APP_CREATION_TIME;
+        
+    }
+
+    lEvent(const Json::Value &jevt){
+    // constructor takes "jsonToEvent" readfile function role
+        eventType = (leventType)jevt["eType"].asInt();
+        val1 = jevt["v1"].asDouble();
+        val2 = jevt["v2"].asDouble();
+        sliderID = jevt["sID"].asInt();
+        eventTime = jevt["eTime"].asLargestInt();
+        
+        // TODO what happens if we try to read one that isn't there?
+        
+    }
+    // new tweak event to json
+    Json::Value eventToJson(){
+        Json::Value jevt;
+        jevt["eType"] = eventType;
+        // convert vector to json array
+        for(auto it = eventData.begin(); it < eventData.end(); it++){
+            jevt["eData"].append(*it);
+        }
+        jevt["eTime"] = eventTime;
+        return jevt;
+    }
+    Json::Value eventToJsonOld(){
+        Json::Value jevt;
+        jevt["eType"] = eventType;
+        // here: should give a certain number of sig figs? 
+        jevt["v1"] = val1;
+        jevt["v2"] = val2;
+        jevt["sID"] = sliderID;
+        jevt["eTime"] = eventTime;
+        return jevt;
+    }
+};
+
+
+//------------------------------------------
+
+class EventLogger{
+public:
+    Poco::Mutex _mutex;
+    
+    int nextUploadNumber;
+    int nextUploadQty;
+    bool loggingEnabled;
+    
+    bool logUploadInProgress;
+    bool serverConnectionOK;
+    bool consentGiven;
+    bool questionnaireCompleted;
+    bool questionnaireUploaded;
+    
+    unsigned int deviceID;
+    unsigned int totalInteractionTime, savedInteractionTime, sessionTime, sessionStartTime;
+    string userName; // not unique
+    string questionnaireComments;
+// constr
+    EventLogger();
+    
+// public methods:
+    void startLoadAll();
+    void exitAndSave();
+    void setUsername(const char *u);
+    string getUsername(){
+        return userName;
+    }
+    void newUser();
+    void logEvent(const leventType& evtType);
+    void logEvent(const leventType& evtType, const vector<int> eventData);
+    
+    void questionnaireAnswersObtained(vector<int> answers, const char* userComments);
+    void urlResponse(ofHttpResponse & response);
+    
+    void questionnaireOK();
+    void eventlogOK();
+    void testConnectionOK();
+    void questionnaireNotOK();
+    void eventlogNotOK();
+    void testConnectionNotOK();
+    
+    void printAll();
+    void saveSessionToFile();
+
+private:
+    void thinnedSliderEvent(lEvent newEvent);
+    vector<lEvent> theEvents; // all logged but not uploaded events
+
+    vector<int> questionnaireAnswers;
+
+// private methods
+    void testConnection();
+    void checkLogFile();
+    void deleteLogs(); // new user
+    bool uploadEventLog(bool async);
+    void firstEverAppOpen();
+    void loadExistingLogFile(const string &jsonFile);
+    void uploadQuestionnaire();
+    bool sendToServer(string functionName, Json::Value jsonData, bool async);
+
+    Json::Value logsToJson();
+    Json::Value questionnaireToJson();
+
+    
+    template<class T> bool matchID(T thing);
+    bool matchID2();
+    //
+    ServerComms *serverComms;
+    
+};
+
+    
+    //---------------------------------------------------------------------------
+   
+
+#endif /* defined(__oscSenderExample__eventLogger__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eventLogger.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,547 @@
+//
+//  eventLogger.mm
+//  oscSenderExample
+//
+//  Created by Robert Tubb on 05/11/2012.
+//
+//
+
+//---------------------------------------------------------------------------
+#include "eventLogger.h"
+
+EventLogger eventLogger;
+
+//---------------------------------------------------------------------------
+EventLogger::EventLogger(){
+    
+    consentGiven = true; // unless told otherwise firstAppOpen
+    loggingEnabled = true;
+    serverConnectionOK = false;
+    questionnaireCompleted = false;
+    questionnaireUploaded = false;
+    logUploadInProgress = false;
+    
+    nextUploadQty = UPLOAD_CHUNK_SIZE; // amount of data uploaded is always more than UPLOAD_CHUNK_SIZE events
+    serverComms = [[ServerComms alloc] init];
+    
+}
+//---------------------------------------------------------------------------
+void EventLogger::startLoadAll(){
+    
+    // TODO pilot doesn't check existing
+    //loadExistingLogFile(ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME);
+    
+    
+    sessionStartTime = ofGetSystemTime();
+    
+    // TODO pilot
+    // testConnection();
+    
+    // if we have a back log of events upload them
+    if(theEvents.size() > nextUploadQty && ! logUploadInProgress){
+        //try to upload
+        
+        // TODO pilot doesn't upload
+        //uploadEventLog(true);
+    }
+    
+    if(questionnaireCompleted && !questionnaireUploaded){
+        uploadQuestionnaire();
+    }
+    
+    //TODO if questionnaire wasn't reached but still opened then set the timer to something sensible
+    
+    //timer.setInteractionTime(savedInteractionTime);
+    //timer.setOrderFromPrevious(interfaceOrder);
+    
+    // for now sod it, start from scratch
+    if(!questionnaireCompleted){
+        cout<<"Questionnaire NOT completed - first APP open called\n";
+        firstEverAppOpen();
+    }
+ 
+}
+//---------------------------------------------------------------------------
+void EventLogger::testConnection(){
+    Json::Value root;
+    root["x"] = "y";
+    cout << "testConnection\n";
+    sendToServer("testConnection", root, true);
+    
+}
+//---------------------------------------------------------------------------
+// this reads the persistent log file , checks if we've used the app before and
+// if we've answered questionnaire or not
+
+// should just store stuff. the start up state should be handled by testAPp
+
+void EventLogger::loadExistingLogFile(const string &jsonFile){
+    Json::Value root;
+    Json::Reader reader;
+    
+    /////////////
+    // read file
+    
+    ifstream theFile(jsonFile.c_str());
+    stringstream fileText;
+    string line;
+    if(!theFile){
+        cout<<"No event log file found - first APP open called\n";
+        firstEverAppOpen();
+        return;
+    }else{
+        while(theFile){
+            theFile >> line;
+            // cout << line;  // lots!!!!
+            fileText << line;
+        }
+        theFile.close();
+    }
+    
+    cout << "size of log 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 event log JSON: \n"
+        << reader.getFormattedErrorMessages();
+        return;
+    }
+    
+    /////////////////
+    // now put user deets into variables
+    
+    userName = root["userName"].asString();
+    deviceID = root["deviceID"].asLargestInt();
+    nextUploadNumber = root["uploadNumber"].asInt();
+    savedInteractionTime = root["savedInteractionTime"].asLargestInt();
+    questionnaireCompleted = root["questionnaireCompleted"].asBool();
+    questionnaireUploaded = root["questionnaireUploaded"].asBool();
+    
+    // check for unuploaded evts
+    const Json::Value jlogs = root["events"];
+    
+    for ( int index = 0; index < jlogs.size(); ++index ) theEvents.push_back(lEvent(jlogs[index]));
+    
+    
+    //////////////
+    
+    if(questionnaireCompleted && !questionnaireUploaded){
+        // then read it in and upload it
+        Json::Value JQ = root["questionnaire"];
+        Json::Value JArray = JQ["qAnswers"];
+        if(JArray.size() < 2){
+            cout << "Error - status of questionnaire is wierd\n";
+        }
+        for ( unsigned int i = 0; i < JArray.size(); i++ )
+        {
+            questionnaireAnswers.push_back(JArray[i].asInt());
+        }
+        questionnaireComments = JQ["comments"].toStyledString();
+        //uploadQuestionnaire();
+    }
+    
+    // TODO interaction time seems to be balls
+    cout << "Total interaction time: " << savedInteractionTime << '\n';
+    
+}
+
+//---------------------------------------------------------------------------
+
+void EventLogger::firstEverAppOpen(){
+    
+    nextUploadNumber = 0;
+    deviceID = ofGetSystemTimeMicros();
+    savedInteractionTime = 0;
+    questionnaireCompleted = false;
+    questionnaireUploaded = false;
+    
+}
+
+
+//---------------------------------------------------------------------------
+void EventLogger::questionnaireAnswersObtained(vector<int> answers, const char* userComments){
+    
+    questionnaireCompleted = true;
+    questionnaireAnswers = answers;
+    questionnaireComments = userComments;
+    uploadQuestionnaire();
+    logEvent(QUESTIONNAIRE_COMPLETED);
+    
+}
+//---------------------------------------------------------------------------
+void EventLogger::uploadQuestionnaire(){
+    // show indicator
+    cout << "^^^^^^^^ UPLOADING QUESTIONNAIRE ^^^^^^^^ \n";
+    cout << questionnaireToJson() << "\n";
+    sendToServer("questionnaire", questionnaireToJson(), true);
+    
+}
+//---------------------------------------------------------------------------
+bool EventLogger::sendToServer(string functionName, Json::Value jsonData, bool async = false){
+    
+    Json::FastWriter writer;
+    string jsontext = writer.write( jsonData );
+    
+    // remove newline
+    if (!jsontext.empty() && jsontext[jsontext.length()-1] == '\n') {
+        jsontext.erase(jsontext.length()-1);
+    }
+    ostringstream jd;
+    jd << jsontext;
+    NSString *theData = [NSString stringWithUTF8String:jd.str().c_str()];
+    NSString *theType = [NSString stringWithUTF8String:functionName.c_str()];
+    
+    if(async){
+        [serverComms doPostRequest:theType withData:theData];
+    }else{
+        bool success = [serverComms doSyncPostRequest:theType withData:theData];
+        return success;
+    }
+    
+}
+//-----------------------------
+void EventLogger::questionnaireOK(){
+    questionnaireUploaded = true;
+    questionnaireComments = "";
+}
+//-----------------------------
+void EventLogger::eventlogOK(){
+    // COMMENT THIS IF UPLAODING FROM IPAD TO XCODE
+    
+    // it's a bad idea to do this in another thread...
+    theEvents.clear();
+    cout << "EVENT LOG UPLOAD SUCCESS\n";
+    nextUploadNumber++;
+    logUploadInProgress = false;
+}
+//-----------------------------
+void EventLogger::testConnectionOK(){
+    cout << "^^^^^^^^ server connection OK ^^^^^^^^ \n";
+    serverConnectionOK = true;
+}
+//-----------------------------
+void EventLogger::questionnaireNotOK(){
+    cout << "XXXXX questionnaire  NOT OK XXXXXXX \n";
+    questionnaireUploaded = false;
+}
+//-----------------------------
+void EventLogger::eventlogNotOK(){
+    // try later
+    cout << "XXXXX event log  NOT OK XXXXXXX \n";
+    nextUploadQty += UPLOAD_CHUNK_SIZE;
+    logUploadInProgress = false;
+}
+//-----------------------------
+void EventLogger::testConnectionNotOK(){
+    cout << "XXXXX server connection NOT OK XXXXXXX \n";
+    serverConnectionOK = false;
+    // alert?
+    
+}
+
+
+//---------------------------------------------------------------------------
+
+bool EventLogger::uploadEventLog(bool async){
+    
+    // show indicator
+    logUploadInProgress = true;
+    cout << "^^^^^^^^  ATTEMPTING TO UPLOAD " << theEvents.size() << " EVENTS ^^^^^^^^ .\n";
+    if(!async){
+        bool success = sendToServer("eventlog", logsToJson(), async);
+        if(!success){
+            // try later
+            nextUploadQty += UPLOAD_CHUNK_SIZE;
+            // increment upload number?
+        }else{
+            
+            // if success - clear memory
+            // IF UPLAODING FROM IPAD TO XCODE COMMENT OUT
+            theEvents.clear();
+            cout << "UPLOAD SUCCESS\n";
+            nextUploadNumber++;
+        }
+        logUploadInProgress = false;
+        return success;
+    }else{
+        sendToServer("eventlog", logsToJson(), async);
+    }
+}
+//---------------------------------------------------------------------------
+// only called when doing supervised tests
+void EventLogger::newUser(){
+    // store old stuff
+    
+    saveSessionToFile();
+    cout<<"setup new user\n";
+    deleteLogs();
+    nextUploadNumber = 0;
+    deviceID = ofGetSystemTimeMicros();
+    savedInteractionTime = 0;
+    totalInteractionTime = 0;
+    sessionStartTime = ofGetSystemTime();
+    questionnaireCompleted = false;
+    questionnaireUploaded = false;
+    
+    //((testApp *)ofGetAppPtr())->showIntro();
+    
+}
+//---------------------------------------------------------------------------
+// called from alertView OK in iViewController
+void EventLogger::setUsername(const char *u){
+    userName = u;
+    
+}
+//---------------------------------------------------------------------------
+//new tweakathlon event logger with vector
+void EventLogger::logEvent(const leventType& evtType, const vector<int> eventData){
+    Poco::Mutex::ScopedLock lock(_mutex);
+    if(!loggingEnabled) return;
+    
+    switch ( evtType ) {
+            
+//        case CANDIDATE_PARAM_ADJUSTED:
+//            // TODO thinning here. maybe. was a pain in the butt.
+//            thinnedSliderEvent(lEvent(evtType,eventData));
+//            break;
+        default:
+            // default is just an event type with vector of ints. matlab will know what they are.
+            
+            
+            theEvents.push_back(lEvent(evtType, eventData));
+          
+            break;
+    }
+    
+    if(theEvents.size() > nextUploadQty && !logUploadInProgress){
+        //try to upload asynchronously
+        // TODO pilot doesn't upload
+        //uploadEventLog(true);
+    }
+    //TODO thiswrong?
+    totalInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime); // milliseconds
+    
+}
+//---------------------------------------------------------------------------
+// OLD SONIC ZOOM EVT - still used for simple events with no data
+void EventLogger::logEvent(const leventType& evtType){
+    Poco::Mutex::ScopedLock lock(_mutex);
+    if(!loggingEnabled) return;
+    
+    switch ( evtType ) {
+            // data thinning here
+        case APP_LOADED:
+            theEvents.push_back(lEvent(evtType));
+        default:
+            // default is just an event type with vector of ints. matlab will know what they are.
+
+         
+            theEvents.push_back(lEvent(evtType));
+          
+    }
+    
+    if(theEvents.size() > nextUploadQty && !logUploadInProgress){
+        //try to upload asynchronously
+        // TODO pilot doesn't upload
+        //uploadEventLog(true);
+    }
+    //TODO thiswrong?
+    totalInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime); // milliseconds
+    
+}
+// UnaryPredicate
+template <class T>
+bool EventLogger::matchID(T thing){
+    return true;
+}
+bool EventLogger::matchID2(){
+    return true;
+}
+//---------------------------------------------------------------------------
+void EventLogger::thinnedSliderEvent(lEvent newEvent){
+    static vector<lEvent> unloggedEventsCache; // list of all different slider events
+    static int eventCounter = 0;
+    
+    // if first event then log it.
+    if(theEvents.size() == 0){
+        theEvents.push_back(newEvent);
+    }
+    
+    // look for last event in the cache that had this mappingID
+    cout << unloggedEventsCache.size() << endl;
+    
+    vector<lEvent>::iterator lastMatching;
+    for(lastMatching = unloggedEventsCache.begin();
+        lastMatching != unloggedEventsCache.end() && ( (*lastMatching).eventData[0] != newEvent.eventData[0]);
+        lastMatching++);
+    
+    
+    if (lastMatching != unloggedEventsCache.end()){
+        //cout << "matching id logevent: " << (*lastMatching).eventData[0] << " " << newEvent.eventData[0] << endl;
+        // we have another, check gap
+        int gap = newEvent.eventTime - (*lastMatching).eventTime;
+        if(gap > 300){
+            theEvents.push_back((*lastMatching));
+            
+            // also log new slider evt
+            theEvents.push_back(newEvent);
+            eventCounter = 0;
+            
+        }else if(eventCounter >= EVENT_THIN_FACTOR){ // otherwise only record every Nth event
+            theEvents.push_back(newEvent);
+            eventCounter = 0;
+            // DELETE THAT PREVIOUS EVENT
+            unloggedEventsCache.erase(lastMatching);
+            
+        }else{
+            // ignore for now but put in unlogged
+            unloggedEventsCache.push_back(newEvent);
+        }
+
+    }else{
+        // this event type wasnt in the cache
+        if(eventCounter >= EVENT_THIN_FACTOR){ // otherwise only record every Nth event
+            theEvents.push_back(newEvent);
+            eventCounter = 0;
+        }else{
+            unloggedEventsCache.push_back(newEvent);
+        }
+        
+    }
+    // always count the new one
+    eventCounter++;
+   
+    
+    
+}
+
+//--------------------------------------------------------------------
+// called from newUser
+void EventLogger::deleteLogs(){
+    // the
+    theEvents.clear();
+    string fname = ofxiPhoneGetDocumentsDirectory() + EVENT_LOG_FILENAME;
+    ofFile logFile(fname,ofFile::WriteOnly);
+    logFile << "";
+    logFile.close();
+}
+//---------------------------------------------------------------------------
+
+void EventLogger::exitAndSave(){
+    
+    if(!consentGiven){
+        Json::Value jlogs = logsToJson();
+        // try to upload TODO (no - might hang and prevent exit???)
+        
+        // TODO pilot doesn't upload
+        //       uploadEventLog(true);
+        return;
+    }
+    
+    savedInteractionTime = savedInteractionTime + (ofGetSystemTime() - sessionStartTime);
+    // save user details
+    string fname = ofxiPhoneGetDocumentsDirectory() + userName + '_' + EVENT_LOG_FILENAME;
+    
+    // try to upload
+    // do it sync because event list needs to be cleared to prevent saving on device
+    
+    // TODO for pilot store to ipad
+    // uploadEventLog(false);
+    
+    // write to file
+    // json without the logs that were uploaded!
+    Json::Value jlogs = logsToJson();
+    ofFile logFile(fname,ofFile::WriteOnly);
+    logFile << jlogs;
+    cout << jlogs;
+    logFile.close();
+    
+}
+//---------------------------------------------------------------------------
+
+Json::Value EventLogger::logsToJson(){
+    // put all logged events into Json formatted string
+    Json::Value root;
+    
+    vector<lEvent>::iterator eventIter;
+    
+    root["programVersion"] = PROGRAM_VERSION;
+    root["userName"] = userName;
+    root["deviceID"] = deviceID;
+    root["uploadNumber"] = nextUploadNumber;
+    root["savedInteractionTime"] = savedInteractionTime;
+    root["questionnaireCompleted"] = questionnaireCompleted;
+    root["questionnaireUploaded"] = questionnaireUploaded;
+    
+    // this can mess up matlab script if it doesn't find this field
+    root["questionnaire"] = questionnaireToJson();
+    
+    
+    int i = 0;
+    for(eventIter = theEvents.begin(); eventIter < theEvents.end(); eventIter++){
+        root["events"][i] = (*eventIter).eventToJson();
+        i++;
+    }
+    root["numEventsHere"] = i;
+    return root;
+}
+
+//---------------------------------------------------------------------------
+
+Json::Value EventLogger::questionnaireToJson(){
+    // put all answers into Json formatted string
+    Json::Value root;
+    
+    vector<int>::iterator aIter;
+    
+    Json::Value questionnaire;
+    
+    int i = 0;
+    for(aIter = questionnaireAnswers.begin(); aIter < questionnaireAnswers.end(); aIter++){
+        questionnaire[i] = (*aIter);
+        i++;
+    }
+    
+    root["qAnswers"] = questionnaire;
+    root["comments"] = questionnaireComments;
+    root["userName"] = userName;
+    root["deviceID"] = deviceID;
+    root["programVersion"] = PROGRAM_VERSION;
+    
+    return root;
+}
+
+//---------------------------------------------------------------------------
+void EventLogger::printAll(){
+    cout << "-----------------ALL LOGGED EVENTS----------------- \n";
+    vector<lEvent>::iterator evIter;
+    cout << logsToJson() << "\n";
+    cout << "---------------------QUESTIONNAIRE---------------- \n";
+    cout << questionnaireToJson() << "\n";
+};
+//---------------------------------------------------------------------------
+
+void EventLogger::saveSessionToFile(){
+    stringstream fn;
+    fn << ofxiPhoneGetDocumentsDirectory() << userName << '_' << sessionStartTime << "_BACKUP.json";
+    
+    string fname = fn.str(); //ofxiPhoneGetDocumentsDirectory() + userName + '_' + "TESTSAVE.json";
+    
+    // write to file
+    // json without the logs that were uploaded!
+    Json::Value jlogs = logsToJson();
+    ofFile logFile(fname,ofFile::WriteOnly);
+    logFile << jlogs;
+    logFile.close();
+    
+}
+//----------------------------------------------------------------------------
+
+// this builds up a file incrementally, which can be recovered on crash
+//void EventLogger::appendToFile(){
+//    
+//    
+//}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/globalVariables.cpp	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,3 @@
+#include "globalVariables.h"
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/globalVariables.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,39 @@
+//
+//  globalVariables.h
+//  emptyExample
+//
+//  Created by Robert Tubb on 22/05/2013.
+//
+//
+
+#pragma once
+#include "ofMain.h"
+
+// magic numbers for event ids
+#define TRIGGER_TARGET_ID   99236082
+#define TRIGGER_CANDIDATE_ID   99233256
+#define RANDOMISE_TARGET_ID 99764448
+#define SUBMIT_CANDIDATE    99371538
+#define START_ALTERNATE_ID  99956352
+#define SHOW_HIDE_PANEL     99857329
+#define SHOW_HIDE_HINT      99724563
+#define NEW_TEST_ID         99163527
+#define CRAP_TEST_ID        99817364
+#define GOOD_TEST_ID        99090378
+#define RESTART_EXPERIMENT_ID 99658290
+#define SPEED_CHANGE_ID     99573012
+#define VOLUME_CHANGE_ID    99263748
+#define ALTERNATION_SPEED 180 // ms that target / candidate sounds play
+// globles
+
+#define TOTAL_NUM_PARAMS 6
+#define TARGET_SCORE_CC_BAND 6 // number of cc vals per target band in dartboard
+typedef enum {TOUCH_DOWN, TOUCH_MOVED, TOUCH_UP} touchType;
+typedef enum {INTRO,QUESTIONNAIRE, HELP, TEST_IN_PROGRESS, SCORE_AND_HINT, COUNT_DOWN, READY_FOR_NEXT} interfaceType;
+
+typedef enum {SLIDER, XYPAD, BUTTON, LEAP3D} controllerType;
+typedef enum {SEQUENTIAL, REVISITABLE, SIMULTANEOUS, MULTI_SIMPLE, MULTI_COMPLEX} controlPanelType;
+
+typedef enum {FILL,LINE, BLOB} SliderType;
+
+typedef enum {SMALLFONT, MEDIUMFONT, LARGEFONT} FontSize;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/autolink.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,19 @@
+#ifndef JSON_AUTOLINK_H_INCLUDED
+# define JSON_AUTOLINK_H_INCLUDED
+
+# include "config.h"
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/cpptl_autolink.h>
+# endif
+
+# if !defined(JSON_NO_AUTOLINK)  &&  !defined(JSON_DLL_BUILD)  &&  !defined(JSON_IN_CPPTL)
+#  define CPPTL_AUTOLINK_NAME "json"
+#  undef CPPTL_AUTOLINK_DLL
+#  ifdef JSON_DLL
+#   define CPPTL_AUTOLINK_DLL
+#  endif
+#  include "autolink.h"
+# endif
+
+#endif // JSON_AUTOLINK_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/config.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,43 @@
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL!
+//#  define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/config.h>
+#  ifndef JSON_USE_CPPTL
+#   define JSON_USE_CPPTL 1
+#  endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+#  define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+#  define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+#  define JSON_API __declspec(dllimport)
+# else
+#  define JSON_API
+# endif
+
+#endif // JSON_CONFIG_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/features.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,42 @@
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+# define CPPTL_JSON_FEATURES_H_INCLUDED
+
+# include "forwards.h"
+
+namespace Json {
+
+   /** \brief Configuration passed to reader and writer.
+    * This configuration object can be used to force the Reader or Writer
+    * to behave in a standard conforming way.
+    */
+   class JSON_API Features
+   {
+   public:
+      /** \brief A configuration that allows all features and assumes all strings are UTF-8.
+       * - C & C++ comments are allowed
+       * - Root object can be any JSON value
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features all();
+
+      /** \brief A configuration that is strictly compatible with the JSON specification.
+       * - Comments are forbidden.
+       * - Root object must be either an array or an object value.
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features strictMode();
+
+      /** \brief Initialize the configuration like JsonConfig::allFeatures;
+       */
+      Features();
+
+      /// \c true if comments are allowed. Default: \c true.
+      bool allowComments_;
+
+      /// \c true if root must be either an array or an object value. Default: \c false.
+      bool strictRoot_;
+   };
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/json-forwards.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,249 @@
+/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
+/// It is intented to be used with #include <json/json-forwards.h>
+/// This header provides forward declaration for all JsonCpp types.
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
+# define JSON_FORWARD_AMALGATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGATED
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
+//#  define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/config.h>
+#  ifndef JSON_USE_CPPTL
+#   define JSON_USE_CPPTL 1
+#  endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+#  define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+#  define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+#  define JSON_API __declspec(dllimport)
+# else
+#  define JSON_API
+# endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER)  &&  _MSC_VER <= 1200 // MSVC 6
+// Microsoft Visual Studio 6 only support conversion from __int64 to double
+// (no conversion from unsigned __int64).
+#define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif // if defined(_MSC_VER)  &&  _MSC_VER < 1200 // MSVC 6
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1500 // MSVC 2008
+/// Indicates that the following function is deprecated.
+# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif
+
+#if !defined(JSONCPP_DEPRECATED)
+# define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+namespace Json {
+   typedef int Int;
+   typedef unsigned int UInt;
+# if defined(JSON_NO_INT64)
+   typedef int LargestInt;
+   typedef unsigned int LargestUInt;
+#  undef JSON_HAS_INT64
+# else // if defined(JSON_NO_INT64)
+   // For Microsoft Visual use specific types as long long is not supported
+#  if defined(_MSC_VER) // Microsoft Visual Studio
+   typedef __int64 Int64;
+   typedef unsigned __int64 UInt64;
+#  else // if defined(_MSC_VER) // Other platforms, use long long
+   typedef long long int Int64;
+   typedef unsigned long long int UInt64;
+#  endif // if defined(_MSC_VER)
+   typedef Int64 LargestInt;
+   typedef UInt64 LargestUInt;
+#  define JSON_HAS_INT64
+# endif // if defined(JSON_NO_INT64)
+} // end namespace Json
+
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+   // writer.h
+   class FastWriter;
+   class StyledWriter;
+
+   // reader.h
+   class Reader;
+
+   // features.h
+   class Features;
+
+   // value.h
+   typedef unsigned int ArrayIndex;
+   class StaticString;
+   class Path;
+   class PathArgument;
+   class Value;
+   class ValueIteratorBase;
+   class ValueIterator;
+   class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   class ValueMapAllocator;
+   class ValueInternalLink;
+   class ValueInternalArray;
+   class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/json.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,1855 @@
+/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).
+/// It is intented to be used with #include <json/json.h>
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_AMALGATED_H_INCLUDED
+# define JSON_AMALGATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+# define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+/// If defined, indicates that Json specific container should be used
+/// (hash table & simple deque container with customizable allocator).
+/// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332
+//#  define JSON_VALUE_USE_INTERNAL_MAP 1
+/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
+/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
+/// as if it was a POD) that may cause some validation tool to report errors.
+/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
+//#  define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
+
+/// If defined, indicates that Json use exception to report invalid type manipulation
+/// instead of C assert macro.
+# define JSON_USE_EXCEPTION 1
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+
+# ifdef JSON_IN_CPPTL
+#  include <cpptl/config.h>
+#  ifndef JSON_USE_CPPTL
+#   define JSON_USE_CPPTL 1
+#  endif
+# endif
+
+# ifdef JSON_IN_CPPTL
+#  define JSON_API CPPTL_API
+# elif defined(JSON_DLL_BUILD)
+#  define JSON_API __declspec(dllexport)
+# elif defined(JSON_DLL)
+#  define JSON_API __declspec(dllimport)
+# else
+#  define JSON_API
+# endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER)  &&  _MSC_VER <= 1200 // MSVC 6
+// Microsoft Visual Studio 6 only support conversion from __int64 to double
+// (no conversion from unsigned __int64).
+#define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif // if defined(_MSC_VER)  &&  _MSC_VER < 1200 // MSVC 6
+
+#if defined(_MSC_VER)  &&  _MSC_VER >= 1500 // MSVC 2008
+/// Indicates that the following function is deprecated.
+# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif
+
+#if !defined(JSONCPP_DEPRECATED)
+# define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+namespace Json {
+   typedef int Int;
+   typedef unsigned int UInt;
+# if defined(JSON_NO_INT64)
+   typedef int LargestInt;
+   typedef unsigned int LargestUInt;
+#  undef JSON_HAS_INT64
+# else // if defined(JSON_NO_INT64)
+   // For Microsoft Visual use specific types as long long is not supported
+#  if defined(_MSC_VER) // Microsoft Visual Studio
+   typedef __int64 Int64;
+   typedef unsigned __int64 UInt64;
+#  else // if defined(_MSC_VER) // Other platforms, use long long
+   typedef long long int Int64;
+   typedef unsigned long long int UInt64;
+#  endif // if defined(_MSC_VER)
+   typedef Int64 LargestInt;
+   typedef UInt64 LargestUInt;
+#  define JSON_HAS_INT64
+# endif // if defined(JSON_NO_INT64)
+} // end namespace Json
+
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+# define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+   // writer.h
+   class FastWriter;
+   class StyledWriter;
+
+   // reader.h
+   class Reader;
+
+   // features.h
+   class Features;
+
+   // value.h
+   typedef unsigned int ArrayIndex;
+   class StaticString;
+   class Path;
+   class PathArgument;
+   class Value;
+   class ValueIteratorBase;
+   class ValueIterator;
+   class ValueConstIterator;
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   class ValueMapAllocator;
+   class ValueInternalLink;
+   class ValueInternalArray;
+   class ValueInternalMap;
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+} // namespace Json
+
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/features.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+# define CPPTL_JSON_FEATURES_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+   /** \brief Configuration passed to reader and writer.
+    * This configuration object can be used to force the Reader or Writer
+    * to behave in a standard conforming way.
+    */
+   class JSON_API Features
+   {
+   public:
+      /** \brief A configuration that allows all features and assumes all strings are UTF-8.
+       * - C & C++ comments are allowed
+       * - Root object can be any JSON value
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features all();
+
+      /** \brief A configuration that is strictly compatible with the JSON specification.
+       * - Comments are forbidden.
+       * - Root object must be either an array or an object value.
+       * - Assumes Value strings are encoded in UTF-8
+       */
+      static Features strictMode();
+
+      /** \brief Initialize the configuration like JsonConfig::allFeatures;
+       */
+      Features();
+
+      /// \c true if comments are allowed. Default: \c true.
+      bool allowComments_;
+
+      /// \c true if root must be either an array or an object value. Default: \c false.
+      bool strictRoot_;
+   };
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/features.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/value.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_H_INCLUDED
+# define CPPTL_JSON_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+# include <string>
+# include <vector>
+
+# ifndef JSON_USE_CPPTL_SMALLMAP
+#  include <map>
+# else
+#  include <cpptl/smallmap.h>
+# endif
+# ifdef JSON_USE_CPPTL
+#  include <cpptl/forwards.h>
+# endif
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+   /** \brief Type of the value held by a Value object.
+    */
+   enum ValueType
+   {
+      nullValue = 0, ///< 'null' value
+      intValue,      ///< signed integer value
+      uintValue,     ///< unsigned integer value
+      realValue,     ///< double value
+      stringValue,   ///< UTF-8 string value
+      booleanValue,  ///< bool value
+      arrayValue,    ///< array value (ordered list)
+      objectValue    ///< object value (collection of name/value pairs).
+   };
+
+   enum CommentPlacement
+   {
+      commentBefore = 0,        ///< a comment placed on the line before a value
+      commentAfterOnSameLine,   ///< a comment just after a value on the same line
+      commentAfter,             ///< a comment on the line after a value (only make sense for root value)
+      numberOfCommentPlacement
+   };
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+   /** \brief Lightweight wrapper to tag static string.
+    *
+    * Value constructor and objectValue member assignement takes advantage of the
+    * StaticString and avoid the cost of string duplication when storing the
+    * string or the member name.
+    *
+    * Example of usage:
+    * \code
+    * Json::Value aValue( StaticString("some text") );
+    * Json::Value object;
+    * static const StaticString code("code");
+    * object[code] = 1234;
+    * \endcode
+    */
+   class JSON_API StaticString
+   {
+   public:
+      explicit StaticString( const char *czstring )
+         : str_( czstring )
+      {
+      }
+
+      operator const char *() const
+      {
+         return str_;
+      }
+
+      const char *c_str() const
+      {
+         return str_;
+      }
+
+   private:
+      const char *str_;
+   };
+
+   /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+    *
+    * This class is a discriminated union wrapper that can represents a:
+    * - signed integer [range: Value::minInt - Value::maxInt]
+    * - unsigned integer (range: 0 - Value::maxUInt)
+    * - double
+    * - UTF-8 string
+    * - boolean
+    * - 'null'
+    * - an ordered list of Value
+    * - collection of name/value pairs (javascript object)
+    *
+    * The type of the held value is represented by a #ValueType and 
+    * can be obtained using type().
+    *
+    * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. 
+    * Non const methods will automatically create the a #nullValue element 
+    * if it does not exist. 
+    * The sequence of an #arrayValue will be automatically resize and initialized 
+    * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+    *
+    * The get() methods can be used to obtanis default value in the case the required element
+    * does not exist.
+    *
+    * It is possible to iterate over the list of a #objectValue values using 
+    * the getMemberNames() method.
+    */
+   class JSON_API Value 
+   {
+      friend class ValueIteratorBase;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      friend class ValueInternalLink;
+      friend class ValueInternalMap;
+# endif
+   public:
+      typedef std::vector<std::string> Members;
+      typedef ValueIterator iterator;
+      typedef ValueConstIterator const_iterator;
+      typedef Json::UInt UInt;
+      typedef Json::Int Int;
+# if defined(JSON_HAS_INT64)
+      typedef Json::UInt64 UInt64;
+      typedef Json::Int64 Int64;
+#endif // defined(JSON_HAS_INT64)
+      typedef Json::LargestInt LargestInt;
+      typedef Json::LargestUInt LargestUInt;
+      typedef Json::ArrayIndex ArrayIndex;
+
+      static const Value null;
+      /// Minimum signed integer value that can be stored in a Json::Value.
+      static const LargestInt minLargestInt;
+      /// Maximum signed integer value that can be stored in a Json::Value.
+      static const LargestInt maxLargestInt;
+      /// Maximum unsigned integer value that can be stored in a Json::Value.
+      static const LargestUInt maxLargestUInt;
+
+      /// Minimum signed int value that can be stored in a Json::Value.
+      static const Int minInt;
+      /// Maximum signed int value that can be stored in a Json::Value.
+      static const Int maxInt;
+      /// Maximum unsigned int value that can be stored in a Json::Value.
+      static const UInt maxUInt;
+
+      /// Minimum signed 64 bits int value that can be stored in a Json::Value.
+      static const Int64 minInt64;
+      /// Maximum signed 64 bits int value that can be stored in a Json::Value.
+      static const Int64 maxInt64;
+      /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
+      static const UInt64 maxUInt64;
+
+   private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+      class CZString 
+      {
+      public:
+         enum DuplicationPolicy 
+         {
+            noDuplication = 0,
+            duplicate,
+            duplicateOnCopy
+         };
+         CZString( ArrayIndex index );
+         CZString( const char *cstr, DuplicationPolicy allocate );
+         CZString( const CZString &other );
+         ~CZString();
+         CZString &operator =( const CZString &other );
+         bool operator<( const CZString &other ) const;
+         bool operator==( const CZString &other ) const;
+         ArrayIndex index() const;
+         const char *c_str() const;
+         bool isStaticString() const;
+      private:
+         void swap( CZString &other );
+         const char *cstr_;
+         ArrayIndex index_;
+      };
+
+   public:
+#  ifndef JSON_USE_CPPTL_SMALLMAP
+      typedef std::map<CZString, Value> ObjectValues;
+#  else
+      typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#  endif // ifndef JSON_USE_CPPTL_SMALLMAP
+# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+   public:
+      /** \brief Create a default Value of the given type.
+
+        This is a very useful constructor.
+        To create an empty array, pass arrayValue.
+        To create an empty object, pass objectValue.
+        Another Value can then be set to this one by assignment.
+    This is useful since clear() and resize() will not alter types.
+
+        Examples:
+    \code
+    Json::Value null_value; // null
+    Json::Value arr_value(Json::arrayValue); // []
+    Json::Value obj_value(Json::objectValue); // {}
+    \endcode
+      */
+      Value( ValueType type = nullValue );
+      Value( Int value );
+      Value( UInt value );
+#if defined(JSON_HAS_INT64)
+      Value( Int64 value );
+      Value( UInt64 value );
+#endif // if defined(JSON_HAS_INT64)
+      Value( double value );
+      Value( const char *value );
+      Value( const char *beginValue, const char *endValue );
+      /** \brief Constructs a value from a static string.
+
+       * Like other value string constructor but do not duplicate the string for
+       * internal storage. The given string must remain alive after the call to this
+       * constructor.
+       * Example of usage:
+       * \code
+       * Json::Value aValue( StaticString("some text") );
+       * \endcode
+       */
+      Value( const StaticString &value );
+      Value( const std::string &value );
+# ifdef JSON_USE_CPPTL
+      Value( const CppTL::ConstString &value );
+# endif
+      Value( bool value );
+      Value( const Value &other );
+      ~Value();
+
+      Value &operator=( const Value &other );
+      /// Swap values.
+      /// \note Currently, comments are intentionally not swapped, for
+      /// both logic and efficiency.
+      void swap( Value &other );
+
+      ValueType type() const;
+
+      bool operator <( const Value &other ) const;
+      bool operator <=( const Value &other ) const;
+      bool operator >=( const Value &other ) const;
+      bool operator >( const Value &other ) const;
+
+      bool operator ==( const Value &other ) const;
+      bool operator !=( const Value &other ) const;
+
+      int compare( const Value &other ) const;
+
+      const char *asCString() const;
+      std::string asString() const;
+# ifdef JSON_USE_CPPTL
+      CppTL::ConstString asConstString() const;
+# endif
+      Int asInt() const;
+      UInt asUInt() const;
+      Int64 asInt64() const;
+      UInt64 asUInt64() const;
+      LargestInt asLargestInt() const;
+      LargestUInt asLargestUInt() const;
+      float asFloat() const;
+      double asDouble() const;
+      bool asBool() const;
+
+      bool isNull() const;
+      bool isBool() const;
+      bool isInt() const;
+      bool isUInt() const;
+      bool isIntegral() const;
+      bool isDouble() const;
+      bool isNumeric() const;
+      bool isString() const;
+      bool isArray() const;
+      bool isObject() const;
+
+      bool isConvertibleTo( ValueType other ) const;
+
+      /// Number of values in array or object
+      ArrayIndex size() const;
+
+      /// \brief Return true if empty array, empty object, or null;
+      /// otherwise, false.
+      bool empty() const;
+
+      /// Return isNull()
+      bool operator!() const;
+
+      /// Remove all object members and array elements.
+      /// \pre type() is arrayValue, objectValue, or nullValue
+      /// \post type() is unchanged
+      void clear();
+
+      /// Resize the array to size elements. 
+      /// New elements are initialized to null.
+      /// May only be called on nullValue or arrayValue.
+      /// \pre type() is arrayValue or nullValue
+      /// \post type() is arrayValue
+      void resize( ArrayIndex size );
+
+      /// Access an array element (zero based index ).
+      /// If the array contains less than index element, then null value are inserted
+      /// in the array so that its size is index+1.
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      Value &operator[]( ArrayIndex index );
+
+      /// Access an array element (zero based index ).
+      /// If the array contains less than index element, then null value are inserted
+      /// in the array so that its size is index+1.
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      Value &operator[]( int index );
+
+      /// Access an array element (zero based index )
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      const Value &operator[]( ArrayIndex index ) const;
+
+      /// Access an array element (zero based index )
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      const Value &operator[]( int index ) const;
+
+      /// If the array contains at least index+1 elements, returns the element value, 
+      /// otherwise returns defaultValue.
+      Value get( ArrayIndex index, 
+                 const Value &defaultValue ) const;
+      /// Return true if index < size().
+      bool isValidIndex( ArrayIndex index ) const;
+      /// \brief Append value to array at the end.
+      ///
+      /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+      Value &append( const Value &value );
+
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const char *key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const char *key ) const;
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const std::string &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const std::string &key ) const;
+      /** \brief Access an object value by name, create a null member if it does not exist.
+
+       * If the object as no entry for that name, then the member name used to store
+       * the new entry is not duplicated.
+       * Example of use:
+       * \code
+       * Json::Value object;
+       * static const StaticString code("code");
+       * object[code] = 1234;
+       * \endcode
+       */
+      Value &operator[]( const StaticString &key );
+# ifdef JSON_USE_CPPTL
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const CppTL::ConstString &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const CppTL::ConstString &key ) const;
+# endif
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const char *key, 
+                 const Value &defaultValue ) const;
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const std::string &key,
+                 const Value &defaultValue ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const CppTL::ConstString &key,
+                 const Value &defaultValue ) const;
+# endif
+      /// \brief Remove and return the named member.  
+      ///
+      /// Do nothing if it did not exist.
+      /// \return the removed Value, or null.
+      /// \pre type() is objectValue or nullValue
+      /// \post type() is unchanged
+      Value removeMember( const char* key );
+      /// Same as removeMember(const char*)
+      Value removeMember( const std::string &key );
+
+      /// Return true if the object has a member named key.
+      bool isMember( const char *key ) const;
+      /// Return true if the object has a member named key.
+      bool isMember( const std::string &key ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return true if the object has a member named key.
+      bool isMember( const CppTL::ConstString &key ) const;
+# endif
+
+      /// \brief Return a list of the member names.
+      ///
+      /// If null, return an empty list.
+      /// \pre type() is objectValue or nullValue
+      /// \post if type() was nullValue, it remains nullValue
+      Members getMemberNames() const;
+
+//# ifdef JSON_USE_CPPTL
+//      EnumMemberNames enumMemberNames() const;
+//      EnumValues enumValues() const;
+//# endif
+
+      /// Comments must be //... or /* ... */
+      void setComment( const char *comment,
+                       CommentPlacement placement );
+      /// Comments must be //... or /* ... */
+      void setComment( const std::string &comment,
+                       CommentPlacement placement );
+      bool hasComment( CommentPlacement placement ) const;
+      /// Include delimiters and embedded newlines.
+      std::string getComment( CommentPlacement placement ) const;
+
+      std::string toStyledString() const;
+
+      const_iterator begin() const;
+      const_iterator end() const;
+
+      iterator begin();
+      iterator end();
+
+   private:
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      inline bool isItemAvailable() const
+      {
+         return itemIsUsed_ == 0;
+      }
+
+      inline void setItemUsed( bool isUsed = true )
+      {
+         itemIsUsed_ = isUsed ? 1 : 0;
+      }
+
+      inline bool isMemberNameStatic() const
+      {
+         return memberNameIsStatic_ == 0;
+      }
+
+      inline void setMemberNameIsStatic( bool isStatic )
+      {
+         memberNameIsStatic_ = isStatic ? 1 : 0;
+      }
+# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+   private:
+      struct CommentInfo
+      {
+         CommentInfo();
+         ~CommentInfo();
+
+         void setComment( const char *text );
+
+         char *comment_;
+      };
+
+      //struct MemberNamesTransform
+      //{
+      //   typedef const char *result_type;
+      //   const char *operator()( const CZString &name ) const
+      //   {
+      //      return name.c_str();
+      //   }
+      //};
+
+      union ValueHolder
+      {
+         LargestInt int_;
+         LargestUInt uint_;
+         double real_;
+         bool bool_;
+         char *string_;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+         ValueInternalArray *array_;
+         ValueInternalMap *map_;
+#else
+         ObjectValues *map_;
+# endif
+      } value_;
+      ValueType type_ : 8;
+      int allocated_ : 1;     // Notes: if declared as bool, bitfield is useless.
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
+      int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
+# endif
+      CommentInfo *comments_;
+   };
+
+
+   /** \brief Experimental and untested: represents an element of the "path" to access a node.
+    */
+   class PathArgument
+   {
+   public:
+      friend class Path;
+
+      PathArgument();
+      PathArgument( ArrayIndex index );
+      PathArgument( const char *key );
+      PathArgument( const std::string &key );
+
+   private:
+      enum Kind
+      {
+         kindNone = 0,
+         kindIndex,
+         kindKey
+      };
+      std::string key_;
+      ArrayIndex index_;
+      Kind kind_;
+   };
+
+   /** \brief Experimental and untested: represents a "path" to access a node.
+    *
+    * Syntax:
+    * - "." => root node
+    * - ".[n]" => elements at index 'n' of root node (an array value)
+    * - ".name" => member named 'name' of root node (an object value)
+    * - ".name1.name2.name3"
+    * - ".[0][1][2].name1[3]"
+    * - ".%" => member name is provided as parameter
+    * - ".[%]" => index is provied as parameter
+    */
+   class Path
+   {
+   public:
+      Path( const std::string &path,
+            const PathArgument &a1 = PathArgument(),
+            const PathArgument &a2 = PathArgument(),
+            const PathArgument &a3 = PathArgument(),
+            const PathArgument &a4 = PathArgument(),
+            const PathArgument &a5 = PathArgument() );
+
+      const Value &resolve( const Value &root ) const;
+      Value resolve( const Value &root, 
+                     const Value &defaultValue ) const;
+      /// Creates the "path" to access the specified node and returns a reference on the node.
+      Value &make( Value &root ) const;
+
+   private:
+      typedef std::vector<const PathArgument *> InArgs;
+      typedef std::vector<PathArgument> Args;
+
+      void makePath( const std::string &path,
+                     const InArgs &in );
+      void addPathInArg( const std::string &path, 
+                         const InArgs &in, 
+                         InArgs::const_iterator &itInArg, 
+                         PathArgument::Kind kind );
+      void invalidPath( const std::string &path, 
+                        int location );
+
+      Args args_;
+   };
+
+
+
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   /** \brief Allocator to customize Value internal map.
+    * Below is an example of a simple implementation (default implementation actually
+    * use memory pool for speed).
+    * \code
+      class DefaultValueMapAllocator : public ValueMapAllocator
+      {
+      public: // overridden from ValueMapAllocator
+         virtual ValueInternalMap *newMap()
+         {
+            return new ValueInternalMap();
+         }
+
+         virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+         {
+            return new ValueInternalMap( other );
+         }
+
+         virtual void destructMap( ValueInternalMap *map )
+         {
+            delete map;
+         }
+
+         virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+         {
+            return new ValueInternalLink[size];
+         }
+
+         virtual void releaseMapBuckets( ValueInternalLink *links )
+         {
+            delete [] links;
+         }
+
+         virtual ValueInternalLink *allocateMapLink()
+         {
+            return new ValueInternalLink();
+         }
+
+         virtual void releaseMapLink( ValueInternalLink *link )
+         {
+            delete link;
+         }
+      };
+    * \endcode
+    */ 
+   class JSON_API ValueMapAllocator
+   {
+   public:
+      virtual ~ValueMapAllocator();
+      virtual ValueInternalMap *newMap() = 0;
+      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
+      virtual void destructMap( ValueInternalMap *map ) = 0;
+      virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
+      virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
+      virtual ValueInternalLink *allocateMapLink() = 0;
+      virtual void releaseMapLink( ValueInternalLink *link ) = 0;
+   };
+
+   /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
+    * \internal previous_ & next_ allows for bidirectional traversal.
+    */
+   class JSON_API ValueInternalLink
+   {
+   public:
+      enum { itemPerLink = 6 };  // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
+      enum InternalFlags { 
+         flagAvailable = 0,
+         flagUsed = 1
+      };
+
+      ValueInternalLink();
+
+      ~ValueInternalLink();
+
+      Value items_[itemPerLink];
+      char *keys_[itemPerLink];
+      ValueInternalLink *previous_;
+      ValueInternalLink *next_;
+   };
+
+
+   /** \brief A linked page based hash-table implementation used internally by Value.
+    * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
+    * list in each bucket to handle collision. There is an addional twist in that
+    * each node of the collision linked list is a page containing a fixed amount of
+    * value. This provides a better compromise between memory usage and speed.
+    * 
+    * Each bucket is made up of a chained list of ValueInternalLink. The last
+    * link of a given bucket can be found in the 'previous_' field of the following bucket.
+    * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
+    * Only the last link of a bucket may contains 'available' item. The last link always
+    * contains at least one element unless is it the bucket one very first link.
+    */
+   class JSON_API ValueInternalMap
+   {
+      friend class ValueIteratorBase;
+      friend class Value;
+   public:
+      typedef unsigned int HashKey;
+      typedef unsigned int BucketIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState
+      {
+         IteratorState() 
+            : map_(0)
+            , link_(0)
+            , itemIndex_(0)
+            , bucketIndex_(0) 
+         {
+         }
+         ValueInternalMap *map_;
+         ValueInternalLink *link_;
+         BucketIndex itemIndex_;
+         BucketIndex bucketIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalMap();
+      ValueInternalMap( const ValueInternalMap &other );
+      ValueInternalMap &operator =( const ValueInternalMap &other );
+      ~ValueInternalMap();
+
+      void swap( ValueInternalMap &other );
+
+      BucketIndex size() const;
+
+      void clear();
+
+      bool reserveDelta( BucketIndex growth );
+
+      bool reserve( BucketIndex newItemCount );
+
+      const Value *find( const char *key ) const;
+
+      Value *find( const char *key );
+
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+      void remove( const char *key );
+
+      void doActualRemove( ValueInternalLink *link, 
+                           BucketIndex index,
+                           BucketIndex bucketIndex );
+
+      ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
+
+      Value &setNewItem( const char *key, 
+                         bool isStatic, 
+                         ValueInternalLink *link, 
+                         BucketIndex index );
+
+      Value &unsafeAdd( const char *key, 
+                        bool isStatic, 
+                        HashKey hashedKey );
+
+      HashKey hash( const char *key ) const;
+
+      int compare( const ValueInternalMap &other ) const;
+
+   private:
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void incrementBucket( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static const char *key( const IteratorState &iterator );
+      static const char *key( const IteratorState &iterator, bool &isStatic );
+      static Value &value( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+
+   private:
+      ValueInternalLink *buckets_;
+      ValueInternalLink *tailLink_;
+      BucketIndex bucketsSize_;
+      BucketIndex itemCount_;
+   };
+
+   /** \brief A simplified deque implementation used internally by Value.
+   * \internal
+   * It is based on a list of fixed "page", each page contains a fixed number of items.
+   * Instead of using a linked-list, a array of pointer is used for fast item look-up.
+   * Look-up for an element is as follow:
+   * - compute page index: pageIndex = itemIndex / itemsPerPage
+   * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
+   *
+   * Insertion is amortized constant time (only the array containing the index of pointers
+   * need to be reallocated when items are appended).
+   */
+   class JSON_API ValueInternalArray
+   {
+      friend class Value;
+      friend class ValueIteratorBase;
+   public:
+      enum { itemsPerPage = 8 };    // should be a power of 2 for fast divide and modulo.
+      typedef Value::ArrayIndex ArrayIndex;
+      typedef unsigned int PageIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState // Must be a POD
+      {
+         IteratorState() 
+            : array_(0)
+            , currentPageIndex_(0)
+            , currentItemIndex_(0) 
+         {
+         }
+         ValueInternalArray *array_;
+         Value **currentPageIndex_;
+         unsigned int currentItemIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalArray();
+      ValueInternalArray( const ValueInternalArray &other );
+      ValueInternalArray &operator =( const ValueInternalArray &other );
+      ~ValueInternalArray();
+      void swap( ValueInternalArray &other );
+
+      void clear();
+      void resize( ArrayIndex newSize );
+
+      Value &resolveReference( ArrayIndex index );
+
+      Value *find( ArrayIndex index ) const;
+
+      ArrayIndex size() const;
+
+      int compare( const ValueInternalArray &other ) const;
+
+   private:
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static Value &dereference( const IteratorState &iterator );
+      static Value &unsafeDereference( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+      static ArrayIndex indexOf( const IteratorState &iterator );
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      void makeIterator( IteratorState &it, ArrayIndex index ) const;
+
+      void makeIndexValid( ArrayIndex index );
+
+      Value **pages_;
+      ArrayIndex size_;
+      PageIndex pageCount_;
+   };
+
+   /** \brief Experimental: do not use. Allocator to customize Value internal array.
+    * Below is an example of a simple implementation (actual implementation use
+    * memory pool).
+      \code
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destruct( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+      \endcode
+    */ 
+   class JSON_API ValueArrayAllocator
+   {
+   public:
+      virtual ~ValueArrayAllocator();
+      virtual ValueInternalArray *newArray() = 0;
+      virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
+      virtual void destructArray( ValueInternalArray *array ) = 0;
+      /** \brief Reallocate array page index.
+       * Reallocates an array of pointer on each page.
+       * \param indexes [input] pointer on the current index. May be \c NULL.
+       *                [output] pointer on the new index of at least 
+       *                         \a minNewIndexCount pages. 
+       * \param indexCount [input] current number of pages in the index.
+       *                   [output] number of page the reallocated index can handle.
+       *                            \b MUST be >= \a minNewIndexCount.
+       * \param minNewIndexCount Minimum number of page the new index must be able to
+       *                         handle.
+       */
+      virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                             ValueInternalArray::PageIndex &indexCount,
+                                             ValueInternalArray::PageIndex minNewIndexCount ) = 0;
+      virtual void releaseArrayPageIndex( Value **indexes, 
+                                          ValueInternalArray::PageIndex indexCount ) = 0;
+      virtual Value *allocateArrayPage() = 0;
+      virtual void releaseArrayPage( Value *value ) = 0;
+   };
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+
+   /** \brief base class for Value iterators.
+    *
+    */
+   class ValueIteratorBase
+   {
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef ValueIteratorBase SelfType;
+
+      ValueIteratorBase();
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
+#else
+      ValueIteratorBase( const ValueInternalArray::IteratorState &state );
+      ValueIteratorBase( const ValueInternalMap::IteratorState &state );
+#endif
+
+      bool operator ==( const SelfType &other ) const
+      {
+         return isEqual( other );
+      }
+
+      bool operator !=( const SelfType &other ) const
+      {
+         return !isEqual( other );
+      }
+
+      difference_type operator -( const SelfType &other ) const
+      {
+         return computeDistance( other );
+      }
+
+      /// Return either the index or the member name of the referenced value as a Value.
+      Value key() const;
+
+      /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+      UInt index() const;
+
+      /// Return the member name of the referenced Value. "" if it is not an objectValue.
+      const char *memberName() const;
+
+   protected:
+      Value &deref() const;
+
+      void increment();
+
+      void decrement();
+
+      difference_type computeDistance( const SelfType &other ) const;
+
+      bool isEqual( const SelfType &other ) const;
+
+      void copy( const SelfType &other );
+
+   private:
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      Value::ObjectValues::iterator current_;
+      // Indicates that iterator is for a null value.
+      bool isNull_;
+#else
+      union
+      {
+         ValueInternalArray::IteratorState array_;
+         ValueInternalMap::IteratorState map_;
+      } iterator_;
+      bool isArray_;
+#endif
+   };
+
+   /** \brief const iterator for object and array value.
+    *
+    */
+   class ValueConstIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef const Value &reference;
+      typedef const Value *pointer;
+      typedef ValueConstIterator SelfType;
+
+      ValueConstIterator();
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueConstIterator( const ValueInternalArray::IteratorState &state );
+      ValueConstIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+      SelfType &operator =( const ValueIteratorBase &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+   /** \brief Iterator for object and array value.
+    */
+   class ValueIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef Value &reference;
+      typedef Value *pointer;
+      typedef ValueIterator SelfType;
+
+      ValueIterator();
+      ValueIterator( const ValueConstIterator &other );
+      ValueIterator( const ValueIterator &other );
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueIterator( const ValueInternalArray::IteratorState &state );
+      ValueIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+
+      SelfType &operator =( const SelfType &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+} // namespace Json
+
+
+#endif // CPPTL_JSON_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/value.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/reader.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include "features.h"
+# include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+    *
+    */
+   class JSON_API Reader
+   {
+   public:
+      typedef char Char;
+      typedef const Char *Location;
+
+      /** \brief Constructs a Reader allowing all features
+       * for parsing.
+       */
+      Reader();
+
+      /** \brief Constructs a Reader allowing the specified feature set
+       * for parsing.
+       */
+      Reader( const Features &features );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const std::string &document, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read.
+       * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. 
+       \               Must be >= beginDoc.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const char *beginDoc, const char *endDoc, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /// \brief Parse from input stream.
+      /// \see Json::operator>>(std::istream&, Json::Value&).
+      bool parse( std::istream &is,
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Returns a user friendly string that list errors in the parsed document.
+       * \return Formatted error message with the list of errors with their location in 
+       *         the parsed document. An empty string is returned if no error occurred
+       *         during parsing.
+       * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+       */
+      JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") 
+      std::string getFormatedErrorMessages() const;
+
+      /** \brief Returns a user friendly string that list errors in the parsed document.
+       * \return Formatted error message with the list of errors with their location in 
+       *         the parsed document. An empty string is returned if no error occurred
+       *         during parsing.
+       */
+      std::string getFormattedErrorMessages() const;
+
+   private:
+      enum TokenType
+      {
+         tokenEndOfStream = 0,
+         tokenObjectBegin,
+         tokenObjectEnd,
+         tokenArrayBegin,
+         tokenArrayEnd,
+         tokenString,
+         tokenNumber,
+         tokenTrue,
+         tokenFalse,
+         tokenNull,
+         tokenArraySeparator,
+         tokenMemberSeparator,
+         tokenComment,
+         tokenError
+      };
+
+      class Token
+      {
+      public:
+         TokenType type_;
+         Location start_;
+         Location end_;
+      };
+
+      class ErrorInfo
+      {
+      public:
+         Token token_;
+         std::string message_;
+         Location extra_;
+      };
+
+      typedef std::deque<ErrorInfo> Errors;
+
+      bool expectToken( TokenType type, Token &token, const char *message );
+      bool readToken( Token &token );
+      void skipSpaces();
+      bool match( Location pattern, 
+                  int patternLength );
+      bool readComment();
+      bool readCStyleComment();
+      bool readCppStyleComment();
+      bool readString();
+      void readNumber();
+      bool readValue();
+      bool readObject( Token &token );
+      bool readArray( Token &token );
+      bool decodeNumber( Token &token );
+      bool decodeString( Token &token );
+      bool decodeString( Token &token, std::string &decoded );
+      bool decodeDouble( Token &token );
+      bool decodeUnicodeCodePoint( Token &token, 
+                                   Location &current, 
+                                   Location end, 
+                                   unsigned int &unicode );
+      bool decodeUnicodeEscapeSequence( Token &token, 
+                                        Location &current, 
+                                        Location end, 
+                                        unsigned int &unicode );
+      bool addError( const std::string &message, 
+                     Token &token,
+                     Location extra = 0 );
+      bool recoverFromError( TokenType skipUntilToken );
+      bool addErrorAndRecover( const std::string &message, 
+                               Token &token,
+                               TokenType skipUntilToken );
+      void skipUntilSpace();
+      Value &currentValue();
+      Char getNextChar();
+      void getLocationLineAndColumn( Location location,
+                                     int &line,
+                                     int &column ) const;
+      std::string getLocationLineAndColumn( Location location ) const;
+      void addComment( Location begin, 
+                       Location end, 
+                       CommentPlacement placement );
+      void skipCommentTokens( Token &token );
+   
+      typedef std::stack<Value *> Nodes;
+      Nodes nodes_;
+      Errors errors_;
+      std::string document_;
+      Location begin_;
+      Location end_;
+      Location current_;
+      Location lastValueEnd_;
+      Value *lastValue_;
+      std::string commentsBefore_;
+      Features features_;
+      bool collectComments_;
+   };
+
+   /** \brief Read from 'sin' into 'root'.
+
+    Always keep comments from the input JSON.
+
+    This can be used to read a file into a particular sub-object.
+    For example:
+    \code
+    Json::Value root;
+    cin >> root["dir"]["file"];
+    cout << root;
+    \endcode
+    Result:
+    \verbatim
+    {
+    "dir": {
+        "file": {
+        // The input stream JSON would be nested here.
+        }
+    }
+    }
+    \endverbatim
+    \throw std::exception on parse error.
+    \see Json::operator<<()
+   */
+   std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/reader.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/writer.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   class Value;
+
+   /** \brief Abstract class for writers.
+    */
+   class JSON_API Writer
+   {
+   public:
+      virtual ~Writer();
+
+      virtual std::string write( const Value &root ) = 0;
+   };
+
+   /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+    *
+    * The JSON document is written in a single line. It is not intended for 'human' consumption,
+    * but may be usefull to support feature such as RPC where bandwith is limited.
+    * \sa Reader, Value
+    */
+   class JSON_API FastWriter : public Writer
+   {
+   public:
+      FastWriter();
+      virtual ~FastWriter(){}
+
+      void enableYAMLCompatibility();
+
+   public: // overridden from Writer
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+
+      std::string document_;
+      bool yamlCompatiblityEnabled_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledWriter: public Writer
+   {
+   public:
+      StyledWriter();
+      virtual ~StyledWriter(){}
+
+   public: // overridden from Writer
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param root Value to serialize.
+       * \return String containing the JSON document that represents the root value.
+       */
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::string document_;
+      std::string indentString_;
+      int rightMargin_;
+      int indentSize_;
+      bool addChildValues_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+        to a stream rather than to a string.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \param indentation Each level will be indented by this amount extra.
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledStreamWriter
+   {
+   public:
+      StyledStreamWriter( std::string indentation="\t" );
+      ~StyledStreamWriter(){}
+
+   public:
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param out Stream to write to. (Can be ostringstream, e.g.)
+       * \param root Value to serialize.
+       * \note There is no point in deriving from Writer, since write() should not return a value.
+       */
+      void write( std::ostream &out, const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::ostream* document_;
+      std::string indentString_;
+      int rightMargin_;
+      std::string indentation_;
+      bool addChildValues_;
+   };
+
+# if defined(JSON_HAS_INT64)
+   std::string JSON_API valueToString( Int value );
+   std::string JSON_API valueToString( UInt value );
+# endif // if defined(JSON_HAS_INT64)
+   std::string JSON_API valueToString( LargestInt value );
+   std::string JSON_API valueToString( LargestUInt value );
+   std::string JSON_API valueToString( double value );
+   std::string JSON_API valueToString( bool value );
+   std::string JSON_API valueToQuotedString( const char *value );
+
+   /// \brief Output using the StyledStreamWriter.
+   /// \see Json::operator>>()
+   std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/writer.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_AMALGATED_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/reader.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,196 @@
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+# define CPPTL_JSON_READER_H_INCLUDED
+
+# include "features.h"
+# include "value.h"
+# include <deque>
+# include <stack>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
+    *
+    */
+   class JSON_API Reader
+   {
+   public:
+      typedef char Char;
+      typedef const Char *Location;
+
+      /** \brief Constructs a Reader allowing all features
+       * for parsing.
+       */
+      Reader();
+
+      /** \brief Constructs a Reader allowing the specified feature set
+       * for parsing.
+       */
+      Reader( const Features &features );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const std::string &document, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
+       * \param document UTF-8 encoded string containing the document to read.
+       * \param root [out] Contains the root value of the document if it was
+       *             successfully parsed.
+       * \param collectComments \c true to collect comment and allow writing them back during
+       *                        serialization, \c false to discard comments.
+       *                        This parameter is ignored if Features::allowComments_
+       *                        is \c false.
+       * \return \c true if the document was successfully parsed, \c false if an error occurred.
+       */
+      bool parse( const char *beginDoc, const char *endDoc, 
+                  Value &root,
+                  bool collectComments = true );
+
+      /// \brief Parse from input stream.
+      /// \see Json::operator>>(std::istream&, Json::Value&).
+      bool parse( std::istream &is,
+                  Value &root,
+                  bool collectComments = true );
+
+      /** \brief Returns a user friendly string that list errors in the parsed document.
+       * \return Formatted error message with the list of errors with their location in 
+       *         the parsed document. An empty string is returned if no error occurred
+       *         during parsing.
+       */
+      std::string getFormatedErrorMessages() const;
+
+   private:
+      enum TokenType
+      {
+         tokenEndOfStream = 0,
+         tokenObjectBegin,
+         tokenObjectEnd,
+         tokenArrayBegin,
+         tokenArrayEnd,
+         tokenString,
+         tokenNumber,
+         tokenTrue,
+         tokenFalse,
+         tokenNull,
+         tokenArraySeparator,
+         tokenMemberSeparator,
+         tokenComment,
+         tokenError
+      };
+
+      class Token
+      {
+      public:
+         TokenType type_;
+         Location start_;
+         Location end_;
+      };
+
+      class ErrorInfo
+      {
+      public:
+         Token token_;
+         std::string message_;
+         Location extra_;
+      };
+
+      typedef std::deque<ErrorInfo> Errors;
+
+      bool expectToken( TokenType type, Token &token, const char *message );
+      bool readToken( Token &token );
+      void skipSpaces();
+      bool match( Location pattern, 
+                  int patternLength );
+      bool readComment();
+      bool readCStyleComment();
+      bool readCppStyleComment();
+      bool readString();
+      void readNumber();
+      bool readValue();
+      bool readObject( Token &token );
+      bool readArray( Token &token );
+      bool decodeNumber( Token &token );
+      bool decodeString( Token &token );
+      bool decodeString( Token &token, std::string &decoded );
+      bool decodeDouble( Token &token );
+      bool decodeUnicodeCodePoint( Token &token, 
+                                   Location &current, 
+                                   Location end, 
+                                   unsigned int &unicode );
+      bool decodeUnicodeEscapeSequence( Token &token, 
+                                        Location &current, 
+                                        Location end, 
+                                        unsigned int &unicode );
+      bool addError( const std::string &message, 
+                     Token &token,
+                     Location extra = 0 );
+      bool recoverFromError( TokenType skipUntilToken );
+      bool addErrorAndRecover( const std::string &message, 
+                               Token &token,
+                               TokenType skipUntilToken );
+      void skipUntilSpace();
+      Value &currentValue();
+      Char getNextChar();
+      void getLocationLineAndColumn( Location location,
+                                     int &line,
+                                     int &column ) const;
+      std::string getLocationLineAndColumn( Location location ) const;
+      void addComment( Location begin, 
+                       Location end, 
+                       CommentPlacement placement );
+      void skipCommentTokens( Token &token );
+   
+      typedef std::stack<Value *> Nodes;
+      Nodes nodes_;
+      Errors errors_;
+      std::string document_;
+      Location begin_;
+      Location end_;
+      Location current_;
+      Location lastValueEnd_;
+      Value *lastValue_;
+      std::string commentsBefore_;
+      Features features_;
+      bool collectComments_;
+   };
+
+   /** \brief Read from 'sin' into 'root'.
+
+    Always keep comments from the input JSON.
+
+    This can be used to read a file into a particular sub-object.
+    For example:
+    \code
+    Json::Value root;
+    cin >> root["dir"]["file"];
+    cout << root;
+    \endcode
+    Result:
+    \verbatim
+    {
+	"dir": {
+	    "file": {
+		// The input stream JSON would be nested here.
+	    }
+	}
+    }
+    \endverbatim
+    \throw std::exception on parse error.
+    \see Json::operator<<()
+   */
+   std::istream& operator>>( std::istream&, Value& );
+
+} // namespace Json
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/value.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,1069 @@
+#ifndef CPPTL_JSON_H_INCLUDED
+# define CPPTL_JSON_H_INCLUDED
+
+# include "forwards.h"
+# include <string>
+# include <vector>
+
+# ifndef JSON_USE_CPPTL_SMALLMAP
+#  include <map>
+# else
+#  include <cpptl/smallmap.h>
+# endif
+# ifdef JSON_USE_CPPTL
+#  include <cpptl/forwards.h>
+# endif
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+   /** \brief Type of the value held by a Value object.
+    */
+   enum ValueType
+   {
+      nullValue = 0, ///< 'null' value
+      intValue,      ///< signed integer value
+      uintValue,     ///< unsigned integer value
+      realValue,     ///< double value
+      stringValue,   ///< UTF-8 string value
+      booleanValue,  ///< bool value
+      arrayValue,    ///< array value (ordered list)
+      objectValue    ///< object value (collection of name/value pairs).
+   };
+
+   enum CommentPlacement
+   {
+      commentBefore = 0,        ///< a comment placed on the line before a value
+      commentAfterOnSameLine,   ///< a comment just after a value on the same line
+      commentAfter,             ///< a comment on the line after a value (only make sense for root value)
+      numberOfCommentPlacement
+   };
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+   /** \brief Lightweight wrapper to tag static string.
+    *
+    * Value constructor and objectValue member assignement takes advantage of the
+    * StaticString and avoid the cost of string duplication when storing the
+    * string or the member name.
+    *
+    * Example of usage:
+    * \code
+    * Json::Value aValue( StaticString("some text") );
+    * Json::Value object;
+    * static const StaticString code("code");
+    * object[code] = 1234;
+    * \endcode
+    */
+   class JSON_API StaticString
+   {
+   public:
+      explicit StaticString( const char *czstring )
+         : str_( czstring )
+      {
+      }
+
+      operator const char *() const
+      {
+         return str_;
+      }
+
+      const char *c_str() const
+      {
+         return str_;
+      }
+
+   private:
+      const char *str_;
+   };
+
+   /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+    *
+    * This class is a discriminated union wrapper that can represents a:
+    * - signed integer [range: Value::minInt - Value::maxInt]
+    * - unsigned integer (range: 0 - Value::maxUInt)
+    * - double
+    * - UTF-8 string
+    * - boolean
+    * - 'null'
+    * - an ordered list of Value
+    * - collection of name/value pairs (javascript object)
+    *
+    * The type of the held value is represented by a #ValueType and 
+    * can be obtained using type().
+    *
+    * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. 
+    * Non const methods will automatically create the a #nullValue element 
+    * if it does not exist. 
+    * The sequence of an #arrayValue will be automatically resize and initialized 
+    * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+    *
+    * The get() methods can be used to obtanis default value in the case the required element
+    * does not exist.
+    *
+    * It is possible to iterate over the list of a #objectValue values using 
+    * the getMemberNames() method.
+    */
+   class JSON_API Value 
+   {
+      friend class ValueIteratorBase;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      friend class ValueInternalLink;
+      friend class ValueInternalMap;
+# endif
+   public:
+      typedef std::vector<std::string> Members;
+      typedef ValueIterator iterator;
+      typedef ValueConstIterator const_iterator;
+      typedef Json::UInt UInt;
+      typedef Json::Int Int;
+      typedef UInt ArrayIndex;
+
+      static const Value null;
+      static const Int minInt;
+      static const Int maxInt;
+      static const UInt maxUInt;
+
+   private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+      class CZString 
+      {
+      public:
+         enum DuplicationPolicy 
+         {
+            noDuplication = 0,
+            duplicate,
+            duplicateOnCopy
+         };
+         CZString( int index );
+         CZString( const char *cstr, DuplicationPolicy allocate );
+         CZString( const CZString &other );
+         ~CZString();
+         CZString &operator =( const CZString &other );
+         bool operator<( const CZString &other ) const;
+         bool operator==( const CZString &other ) const;
+         int index() const;
+         const char *c_str() const;
+         bool isStaticString() const;
+      private:
+         void swap( CZString &other );
+         const char *cstr_;
+         int index_;
+      };
+
+   public:
+#  ifndef JSON_USE_CPPTL_SMALLMAP
+      typedef std::map<CZString, Value> ObjectValues;
+#  else
+      typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#  endif // ifndef JSON_USE_CPPTL_SMALLMAP
+# endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+   public:
+      /** \brief Create a default Value of the given type.
+
+        This is a very useful constructor.
+        To create an empty array, pass arrayValue.
+        To create an empty object, pass objectValue.
+        Another Value can then be set to this one by assignment.
+	This is useful since clear() and resize() will not alter types.
+
+        Examples:
+	\code
+	Json::Value null_value; // null
+	Json::Value arr_value(Json::arrayValue); // []
+	Json::Value obj_value(Json::objectValue); // {}
+	\endcode
+      */
+      Value( ValueType type = nullValue );
+      Value( Int value );
+      Value( UInt value );
+      Value( double value );
+      Value( const char *value );
+      Value( const char *beginValue, const char *endValue );
+      /** \brief Constructs a value from a static string.
+
+       * Like other value string constructor but do not duplicate the string for
+       * internal storage. The given string must remain alive after the call to this
+       * constructor.
+       * Example of usage:
+       * \code
+       * Json::Value aValue( StaticString("some text") );
+       * \endcode
+       */
+      Value( const StaticString &value );
+      Value( const std::string &value );
+# ifdef JSON_USE_CPPTL
+      Value( const CppTL::ConstString &value );
+# endif
+      Value( bool value );
+      Value( const Value &other );
+      ~Value();
+
+      Value &operator=( const Value &other );
+      /// Swap values.
+      /// \note Currently, comments are intentionally not swapped, for
+      /// both logic and efficiency.
+      void swap( Value &other );
+
+      ValueType type() const;
+
+      bool operator <( const Value &other ) const;
+      bool operator <=( const Value &other ) const;
+      bool operator >=( const Value &other ) const;
+      bool operator >( const Value &other ) const;
+
+      bool operator ==( const Value &other ) const;
+      bool operator !=( const Value &other ) const;
+
+      int compare( const Value &other );
+
+      const char *asCString() const;
+      std::string asString() const;
+# ifdef JSON_USE_CPPTL
+      CppTL::ConstString asConstString() const;
+# endif
+      Int asInt() const;
+      UInt asUInt() const;
+      double asDouble() const;
+      bool asBool() const;
+
+      bool isNull() const;
+      bool isBool() const;
+      bool isInt() const;
+      bool isUInt() const;
+      bool isIntegral() const;
+      bool isDouble() const;
+      bool isNumeric() const;
+      bool isString() const;
+      bool isArray() const;
+      bool isObject() const;
+
+      bool isConvertibleTo( ValueType other ) const;
+
+      /// Number of values in array or object
+      UInt size() const;
+
+      /// \brief Return true if empty array, empty object, or null;
+      /// otherwise, false.
+      bool empty() const;
+
+      /// Return isNull()
+      bool operator!() const;
+
+      /// Remove all object members and array elements.
+      /// \pre type() is arrayValue, objectValue, or nullValue
+      /// \post type() is unchanged
+      void clear();
+
+      /// Resize the array to size elements. 
+      /// New elements are initialized to null.
+      /// May only be called on nullValue or arrayValue.
+      /// \pre type() is arrayValue or nullValue
+      /// \post type() is arrayValue
+      void resize( UInt size );
+
+      /// Access an array element (zero based index ).
+      /// If the array contains less than index element, then null value are inserted
+      /// in the array so that its size is index+1.
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      Value &operator[]( UInt index );
+      /// Access an array element (zero based index )
+      /// (You may need to say 'value[0u]' to get your compiler to distinguish
+      ///  this from the operator[] which takes a string.)
+      const Value &operator[]( UInt index ) const;
+      /// If the array contains at least index+1 elements, returns the element value, 
+      /// otherwise returns defaultValue.
+      Value get( UInt index, 
+                 const Value &defaultValue ) const;
+      /// Return true if index < size().
+      bool isValidIndex( UInt index ) const;
+      /// \brief Append value to array at the end.
+      ///
+      /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+      Value &append( const Value &value );
+
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const char *key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const char *key ) const;
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const std::string &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const std::string &key ) const;
+      /** \brief Access an object value by name, create a null member if it does not exist.
+
+       * If the object as no entry for that name, then the member name used to store
+       * the new entry is not duplicated.
+       * Example of use:
+       * \code
+       * Json::Value object;
+       * static const StaticString code("code");
+       * object[code] = 1234;
+       * \endcode
+       */
+      Value &operator[]( const StaticString &key );
+# ifdef JSON_USE_CPPTL
+      /// Access an object value by name, create a null member if it does not exist.
+      Value &operator[]( const CppTL::ConstString &key );
+      /// Access an object value by name, returns null if there is no member with that name.
+      const Value &operator[]( const CppTL::ConstString &key ) const;
+# endif
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const char *key, 
+                 const Value &defaultValue ) const;
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const std::string &key,
+                 const Value &defaultValue ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return the member named key if it exist, defaultValue otherwise.
+      Value get( const CppTL::ConstString &key,
+                 const Value &defaultValue ) const;
+# endif
+      /// \brief Remove and return the named member.  
+      ///
+      /// Do nothing if it did not exist.
+      /// \return the removed Value, or null.
+      /// \pre type() is objectValue or nullValue
+      /// \post type() is unchanged
+      Value removeMember( const char* key );
+      /// Same as removeMember(const char*)
+      Value removeMember( const std::string &key );
+
+      /// Return true if the object has a member named key.
+      bool isMember( const char *key ) const;
+      /// Return true if the object has a member named key.
+      bool isMember( const std::string &key ) const;
+# ifdef JSON_USE_CPPTL
+      /// Return true if the object has a member named key.
+      bool isMember( const CppTL::ConstString &key ) const;
+# endif
+
+      /// \brief Return a list of the member names.
+      ///
+      /// If null, return an empty list.
+      /// \pre type() is objectValue or nullValue
+      /// \post if type() was nullValue, it remains nullValue
+      Members getMemberNames() const;
+
+//# ifdef JSON_USE_CPPTL
+//      EnumMemberNames enumMemberNames() const;
+//      EnumValues enumValues() const;
+//# endif
+
+      /// Comments must be //... or /* ... */
+      void setComment( const char *comment,
+                       CommentPlacement placement );
+      /// Comments must be //... or /* ... */
+      void setComment( const std::string &comment,
+                       CommentPlacement placement );
+      bool hasComment( CommentPlacement placement ) const;
+      /// Include delimiters and embedded newlines.
+      std::string getComment( CommentPlacement placement ) const;
+
+      std::string toStyledString() const;
+
+      const_iterator begin() const;
+      const_iterator end() const;
+
+      iterator begin();
+      iterator end();
+
+   private:
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      inline bool isItemAvailable() const
+      {
+         return itemIsUsed_ == 0;
+      }
+
+      inline void setItemUsed( bool isUsed = true )
+      {
+         itemIsUsed_ = isUsed ? 1 : 0;
+      }
+
+      inline bool isMemberNameStatic() const
+      {
+         return memberNameIsStatic_ == 0;
+      }
+
+      inline void setMemberNameIsStatic( bool isStatic )
+      {
+         memberNameIsStatic_ = isStatic ? 1 : 0;
+      }
+# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+   private:
+      struct CommentInfo
+      {
+         CommentInfo();
+         ~CommentInfo();
+
+         void setComment( const char *text );
+
+         char *comment_;
+      };
+
+      //struct MemberNamesTransform
+      //{
+      //   typedef const char *result_type;
+      //   const char *operator()( const CZString &name ) const
+      //   {
+      //      return name.c_str();
+      //   }
+      //};
+
+      union ValueHolder
+      {
+         Int int_;
+         UInt uint_;
+         double real_;
+         bool bool_;
+         char *string_;
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+         ValueInternalArray *array_;
+         ValueInternalMap *map_;
+#else
+         ObjectValues *map_;
+# endif
+      } value_;
+      ValueType type_ : 8;
+      int allocated_ : 1;     // Notes: if declared as bool, bitfield is useless.
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+      unsigned int itemIsUsed_ : 1;      // used by the ValueInternalMap container.
+      int memberNameIsStatic_ : 1;       // used by the ValueInternalMap container.
+# endif
+      CommentInfo *comments_;
+   };
+
+
+   /** \brief Experimental and untested: represents an element of the "path" to access a node.
+    */
+   class PathArgument
+   {
+   public:
+      friend class Path;
+
+      PathArgument();
+      PathArgument( UInt index );
+      PathArgument( const char *key );
+      PathArgument( const std::string &key );
+
+   private:
+      enum Kind
+      {
+         kindNone = 0,
+         kindIndex,
+         kindKey
+      };
+      std::string key_;
+      UInt index_;
+      Kind kind_;
+   };
+
+   /** \brief Experimental and untested: represents a "path" to access a node.
+    *
+    * Syntax:
+    * - "." => root node
+    * - ".[n]" => elements at index 'n' of root node (an array value)
+    * - ".name" => member named 'name' of root node (an object value)
+    * - ".name1.name2.name3"
+    * - ".[0][1][2].name1[3]"
+    * - ".%" => member name is provided as parameter
+    * - ".[%]" => index is provied as parameter
+    */
+   class Path
+   {
+   public:
+      Path( const std::string &path,
+            const PathArgument &a1 = PathArgument(),
+            const PathArgument &a2 = PathArgument(),
+            const PathArgument &a3 = PathArgument(),
+            const PathArgument &a4 = PathArgument(),
+            const PathArgument &a5 = PathArgument() );
+
+      const Value &resolve( const Value &root ) const;
+      Value resolve( const Value &root, 
+                     const Value &defaultValue ) const;
+      /// Creates the "path" to access the specified node and returns a reference on the node.
+      Value &make( Value &root ) const;
+
+   private:
+      typedef std::vector<const PathArgument *> InArgs;
+      typedef std::vector<PathArgument> Args;
+
+      void makePath( const std::string &path,
+                     const InArgs &in );
+      void addPathInArg( const std::string &path, 
+                         const InArgs &in, 
+                         InArgs::const_iterator &itInArg, 
+                         PathArgument::Kind kind );
+      void invalidPath( const std::string &path, 
+                        int location );
+
+      Args args_;
+   };
+
+   /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
+    *
+    * - makeMemberName() and releaseMemberName() are called to respectively duplicate and
+    *   free an Json::objectValue member name.
+    * - duplicateStringValue() and releaseStringValue() are called similarly to
+    *   duplicate and free a Json::stringValue value.
+    */
+   class ValueAllocator
+   {
+   public:
+      enum { unknown = (unsigned)-1 };
+
+      virtual ~ValueAllocator();
+
+      virtual char *makeMemberName( const char *memberName ) = 0;
+      virtual void releaseMemberName( char *memberName ) = 0;
+      virtual char *duplicateStringValue( const char *value, 
+                                          unsigned int length = unknown ) = 0;
+      virtual void releaseStringValue( char *value ) = 0;
+   };
+
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   /** \brief Allocator to customize Value internal map.
+    * Below is an example of a simple implementation (default implementation actually
+    * use memory pool for speed).
+    * \code
+      class DefaultValueMapAllocator : public ValueMapAllocator
+      {
+      public: // overridden from ValueMapAllocator
+         virtual ValueInternalMap *newMap()
+         {
+            return new ValueInternalMap();
+         }
+
+         virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
+         {
+            return new ValueInternalMap( other );
+         }
+
+         virtual void destructMap( ValueInternalMap *map )
+         {
+            delete map;
+         }
+
+         virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
+         {
+            return new ValueInternalLink[size];
+         }
+
+         virtual void releaseMapBuckets( ValueInternalLink *links )
+         {
+            delete [] links;
+         }
+
+         virtual ValueInternalLink *allocateMapLink()
+         {
+            return new ValueInternalLink();
+         }
+
+         virtual void releaseMapLink( ValueInternalLink *link )
+         {
+            delete link;
+         }
+      };
+    * \endcode
+    */ 
+   class JSON_API ValueMapAllocator
+   {
+   public:
+      virtual ~ValueMapAllocator();
+      virtual ValueInternalMap *newMap() = 0;
+      virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
+      virtual void destructMap( ValueInternalMap *map ) = 0;
+      virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
+      virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
+      virtual ValueInternalLink *allocateMapLink() = 0;
+      virtual void releaseMapLink( ValueInternalLink *link ) = 0;
+   };
+
+   /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
+    * \internal previous_ & next_ allows for bidirectional traversal.
+    */
+   class JSON_API ValueInternalLink
+   {
+   public:
+      enum { itemPerLink = 6 };  // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
+      enum InternalFlags { 
+         flagAvailable = 0,
+         flagUsed = 1
+      };
+
+      ValueInternalLink();
+
+      ~ValueInternalLink();
+
+      Value items_[itemPerLink];
+      char *keys_[itemPerLink];
+      ValueInternalLink *previous_;
+      ValueInternalLink *next_;
+   };
+
+
+   /** \brief A linked page based hash-table implementation used internally by Value.
+    * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
+    * list in each bucket to handle collision. There is an addional twist in that
+    * each node of the collision linked list is a page containing a fixed amount of
+    * value. This provides a better compromise between memory usage and speed.
+    * 
+    * Each bucket is made up of a chained list of ValueInternalLink. The last
+    * link of a given bucket can be found in the 'previous_' field of the following bucket.
+    * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
+    * Only the last link of a bucket may contains 'available' item. The last link always
+    * contains at least one element unless is it the bucket one very first link.
+    */
+   class JSON_API ValueInternalMap
+   {
+      friend class ValueIteratorBase;
+      friend class Value;
+   public:
+      typedef unsigned int HashKey;
+      typedef unsigned int BucketIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState
+      {
+         IteratorState() 
+            : map_(0)
+            , link_(0)
+            , itemIndex_(0)
+            , bucketIndex_(0) 
+         {
+         }
+         ValueInternalMap *map_;
+         ValueInternalLink *link_;
+         BucketIndex itemIndex_;
+         BucketIndex bucketIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalMap();
+      ValueInternalMap( const ValueInternalMap &other );
+      ValueInternalMap &operator =( const ValueInternalMap &other );
+      ~ValueInternalMap();
+
+      void swap( ValueInternalMap &other );
+
+      BucketIndex size() const;
+
+      void clear();
+
+      bool reserveDelta( BucketIndex growth );
+
+      bool reserve( BucketIndex newItemCount );
+
+      const Value *find( const char *key ) const;
+
+      Value *find( const char *key );
+
+      Value &resolveReference( const char *key, 
+                               bool isStatic );
+
+      void remove( const char *key );
+
+      void doActualRemove( ValueInternalLink *link, 
+                           BucketIndex index,
+                           BucketIndex bucketIndex );
+
+      ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
+
+      Value &setNewItem( const char *key, 
+                         bool isStatic, 
+                         ValueInternalLink *link, 
+                         BucketIndex index );
+
+      Value &unsafeAdd( const char *key, 
+                        bool isStatic, 
+                        HashKey hashedKey );
+
+      HashKey hash( const char *key ) const;
+
+      int compare( const ValueInternalMap &other ) const;
+
+   private:
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void incrementBucket( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static const char *key( const IteratorState &iterator );
+      static const char *key( const IteratorState &iterator, bool &isStatic );
+      static Value &value( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+
+   private:
+      ValueInternalLink *buckets_;
+      ValueInternalLink *tailLink_;
+      BucketIndex bucketsSize_;
+      BucketIndex itemCount_;
+   };
+
+   /** \brief A simplified deque implementation used internally by Value.
+   * \internal
+   * It is based on a list of fixed "page", each page contains a fixed number of items.
+   * Instead of using a linked-list, a array of pointer is used for fast item look-up.
+   * Look-up for an element is as follow:
+   * - compute page index: pageIndex = itemIndex / itemsPerPage
+   * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
+   *
+   * Insertion is amortized constant time (only the array containing the index of pointers
+   * need to be reallocated when items are appended).
+   */
+   class JSON_API ValueInternalArray
+   {
+      friend class Value;
+      friend class ValueIteratorBase;
+   public:
+      enum { itemsPerPage = 8 };    // should be a power of 2 for fast divide and modulo.
+      typedef Value::ArrayIndex ArrayIndex;
+      typedef unsigned int PageIndex;
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+      struct IteratorState // Must be a POD
+      {
+         IteratorState() 
+            : array_(0)
+            , currentPageIndex_(0)
+            , currentItemIndex_(0) 
+         {
+         }
+         ValueInternalArray *array_;
+         Value **currentPageIndex_;
+         unsigned int currentItemIndex_;
+      };
+# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+      ValueInternalArray();
+      ValueInternalArray( const ValueInternalArray &other );
+      ValueInternalArray &operator =( const ValueInternalArray &other );
+      ~ValueInternalArray();
+      void swap( ValueInternalArray &other );
+
+      void clear();
+      void resize( ArrayIndex newSize );
+
+      Value &resolveReference( ArrayIndex index );
+
+      Value *find( ArrayIndex index ) const;
+
+      ArrayIndex size() const;
+
+      int compare( const ValueInternalArray &other ) const;
+
+   private:
+      static bool equals( const IteratorState &x, const IteratorState &other );
+      static void increment( IteratorState &iterator );
+      static void decrement( IteratorState &iterator );
+      static Value &dereference( const IteratorState &iterator );
+      static Value &unsafeDereference( const IteratorState &iterator );
+      static int distance( const IteratorState &x, const IteratorState &y );
+      static ArrayIndex indexOf( const IteratorState &iterator );
+      void makeBeginIterator( IteratorState &it ) const;
+      void makeEndIterator( IteratorState &it ) const;
+      void makeIterator( IteratorState &it, ArrayIndex index ) const;
+
+      void makeIndexValid( ArrayIndex index );
+
+      Value **pages_;
+      ArrayIndex size_;
+      PageIndex pageCount_;
+   };
+
+   /** \brief Experimental: do not use. Allocator to customize Value internal array.
+    * Below is an example of a simple implementation (actual implementation use
+    * memory pool).
+      \code
+class DefaultValueArrayAllocator : public ValueArrayAllocator
+{
+public: // overridden from ValueArrayAllocator
+   virtual ~DefaultValueArrayAllocator()
+   {
+   }
+
+   virtual ValueInternalArray *newArray()
+   {
+      return new ValueInternalArray();
+   }
+
+   virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
+   {
+      return new ValueInternalArray( other );
+   }
+
+   virtual void destruct( ValueInternalArray *array )
+   {
+      delete array;
+   }
+
+   virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                          ValueInternalArray::PageIndex &indexCount,
+                                          ValueInternalArray::PageIndex minNewIndexCount )
+   {
+      ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
+      if ( minNewIndexCount > newIndexCount )
+         newIndexCount = minNewIndexCount;
+      void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
+      if ( !newIndexes )
+         throw std::bad_alloc();
+      indexCount = newIndexCount;
+      indexes = static_cast<Value **>( newIndexes );
+   }
+   virtual void releaseArrayPageIndex( Value **indexes, 
+                                       ValueInternalArray::PageIndex indexCount )
+   {
+      if ( indexes )
+         free( indexes );
+   }
+
+   virtual Value *allocateArrayPage()
+   {
+      return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
+   }
+
+   virtual void releaseArrayPage( Value *value )
+   {
+      if ( value )
+         free( value );
+   }
+};
+      \endcode
+    */ 
+   class JSON_API ValueArrayAllocator
+   {
+   public:
+      virtual ~ValueArrayAllocator();
+      virtual ValueInternalArray *newArray() = 0;
+      virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
+      virtual void destructArray( ValueInternalArray *array ) = 0;
+      /** \brief Reallocate array page index.
+       * Reallocates an array of pointer on each page.
+       * \param indexes [input] pointer on the current index. May be \c NULL.
+       *                [output] pointer on the new index of at least 
+       *                         \a minNewIndexCount pages. 
+       * \param indexCount [input] current number of pages in the index.
+       *                   [output] number of page the reallocated index can handle.
+       *                            \b MUST be >= \a minNewIndexCount.
+       * \param minNewIndexCount Minimum number of page the new index must be able to
+       *                         handle.
+       */
+      virtual void reallocateArrayPageIndex( Value **&indexes, 
+                                             ValueInternalArray::PageIndex &indexCount,
+                                             ValueInternalArray::PageIndex minNewIndexCount ) = 0;
+      virtual void releaseArrayPageIndex( Value **indexes, 
+                                          ValueInternalArray::PageIndex indexCount ) = 0;
+      virtual Value *allocateArrayPage() = 0;
+      virtual void releaseArrayPage( Value *value ) = 0;
+   };
+#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
+
+
+   /** \brief base class for Value iterators.
+    *
+    */
+   class ValueIteratorBase
+   {
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef ValueIteratorBase SelfType;
+
+      ValueIteratorBase();
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
+#else
+      ValueIteratorBase( const ValueInternalArray::IteratorState &state );
+      ValueIteratorBase( const ValueInternalMap::IteratorState &state );
+#endif
+
+      bool operator ==( const SelfType &other ) const
+      {
+         return isEqual( other );
+      }
+
+      bool operator !=( const SelfType &other ) const
+      {
+         return !isEqual( other );
+      }
+
+      difference_type operator -( const SelfType &other ) const
+      {
+         return computeDistance( other );
+      }
+
+      /// Return either the index or the member name of the referenced value as a Value.
+      Value key() const;
+
+      /// Return the index of the referenced Value. -1 if it is not an arrayValue.
+      UInt index() const;
+
+      /// Return the member name of the referenced Value. "" if it is not an objectValue.
+      const char *memberName() const;
+
+   protected:
+      Value &deref() const;
+
+      void increment();
+
+      void decrement();
+
+      difference_type computeDistance( const SelfType &other ) const;
+
+      bool isEqual( const SelfType &other ) const;
+
+      void copy( const SelfType &other );
+
+   private:
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      Value::ObjectValues::iterator current_;
+      // Indicates that iterator is for a null value.
+      bool isNull_;
+#else
+      union
+      {
+         ValueInternalArray::IteratorState array_;
+         ValueInternalMap::IteratorState map_;
+      } iterator_;
+      bool isArray_;
+#endif
+   };
+
+   /** \brief const iterator for object and array value.
+    *
+    */
+   class ValueConstIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef const Value &reference;
+      typedef const Value *pointer;
+      typedef ValueConstIterator SelfType;
+
+      ValueConstIterator();
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueConstIterator( const ValueInternalArray::IteratorState &state );
+      ValueConstIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+      SelfType &operator =( const ValueIteratorBase &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+   /** \brief Iterator for object and array value.
+    */
+   class ValueIterator : public ValueIteratorBase
+   {
+      friend class Value;
+   public:
+      typedef unsigned int size_t;
+      typedef int difference_type;
+      typedef Value &reference;
+      typedef Value *pointer;
+      typedef ValueIterator SelfType;
+
+      ValueIterator();
+      ValueIterator( const ValueConstIterator &other );
+      ValueIterator( const ValueIterator &other );
+   private:
+      /*! \internal Use by Value to create an iterator.
+       */
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+      explicit ValueIterator( const Value::ObjectValues::iterator &current );
+#else
+      ValueIterator( const ValueInternalArray::IteratorState &state );
+      ValueIterator( const ValueInternalMap::IteratorState &state );
+#endif
+   public:
+
+      SelfType &operator =( const SelfType &other );
+
+      SelfType operator++( int )
+      {
+         SelfType temp( *this );
+         ++*this;
+         return temp;
+      }
+
+      SelfType operator--( int )
+      {
+         SelfType temp( *this );
+         --*this;
+         return temp;
+      }
+
+      SelfType &operator--()
+      {
+         decrement();
+         return *this;
+      }
+
+      SelfType &operator++()
+      {
+         increment();
+         return *this;
+      }
+
+      reference operator *() const
+      {
+         return deref();
+      }
+   };
+
+
+} // namespace Json
+
+
+#endif // CPPTL_JSON_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/json/writer.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,174 @@
+#ifndef JSON_WRITER_H_INCLUDED
+# define JSON_WRITER_H_INCLUDED
+
+# include "value.h"
+# include <vector>
+# include <string>
+# include <iostream>
+
+namespace Json {
+
+   class Value;
+
+   /** \brief Abstract class for writers.
+    */
+   class JSON_API Writer
+   {
+   public:
+      virtual ~Writer();
+
+      virtual std::string write( const Value &root ) = 0;
+   };
+
+   /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
+    *
+    * The JSON document is written in a single line. It is not intended for 'human' consumption,
+    * but may be usefull to support feature such as RPC where bandwith is limited.
+    * \sa Reader, Value
+    */
+   class JSON_API FastWriter : public Writer
+   {
+   public:
+      FastWriter();
+      virtual ~FastWriter(){}
+
+      void enableYAMLCompatibility();
+
+   public: // overridden from Writer
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+
+      std::string document_;
+      bool yamlCompatiblityEnabled_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledWriter: public Writer
+   {
+   public:
+      StyledWriter();
+      virtual ~StyledWriter(){}
+
+   public: // overridden from Writer
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param root Value to serialize.
+       * \return String containing the JSON document that represents the root value.
+       */
+      virtual std::string write( const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::string document_;
+      std::string indentString_;
+      int rightMargin_;
+      int indentSize_;
+      bool addChildValues_;
+   };
+
+   /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
+        to a stream rather than to a string.
+    *
+    * The rules for line break and indent are as follow:
+    * - Object value:
+    *     - if empty then print {} without indent and line break
+    *     - if not empty the print '{', line break & indent, print one value per line
+    *       and then unindent and line break and print '}'.
+    * - Array value:
+    *     - if empty then print [] without indent and line break
+    *     - if the array contains no object value, empty array or some other value types,
+    *       and all the values fit on one lines, then print the array on a single line.
+    *     - otherwise, it the values do not fit on one line, or the array contains
+    *       object or non empty array, then print one value per line.
+    *
+    * If the Value have comments then they are outputed according to their #CommentPlacement.
+    *
+    * \param indentation Each level will be indented by this amount extra.
+    * \sa Reader, Value, Value::setComment()
+    */
+   class JSON_API StyledStreamWriter
+   {
+   public:
+      StyledStreamWriter( std::string indentation="\t" );
+      ~StyledStreamWriter(){}
+
+   public:
+      /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+       * \param out Stream to write to. (Can be ostringstream, e.g.)
+       * \param root Value to serialize.
+       * \note There is no point in deriving from Writer, since write() should not return a value.
+       */
+      void write( std::ostream &out, const Value &root );
+
+   private:
+      void writeValue( const Value &value );
+      void writeArrayValue( const Value &value );
+      bool isMultineArray( const Value &value );
+      void pushValue( const std::string &value );
+      void writeIndent();
+      void writeWithIndent( const std::string &value );
+      void indent();
+      void unindent();
+      void writeCommentBeforeValue( const Value &root );
+      void writeCommentAfterValueOnSameLine( const Value &root );
+      bool hasCommentForValue( const Value &value );
+      static std::string normalizeEOL( const std::string &text );
+
+      typedef std::vector<std::string> ChildValues;
+
+      ChildValues childValues_;
+      std::ostream* document_;
+      std::string indentString_;
+      int rightMargin_;
+      std::string indentation_;
+      bool addChildValues_;
+   };
+
+   std::string JSON_API valueToString( Int value );
+   std::string JSON_API valueToString( UInt value );
+   std::string JSON_API valueToString( double value );
+   std::string JSON_API valueToString( bool value );
+   std::string JSON_API valueToQuotedString( const char *value );
+
+   /// \brief Output using the StyledStreamWriter.
+   /// \see Json::operator>>()
+   std::ostream& operator<<( std::ostream&, const Value &root );
+
+} // namespace Json
+
+
+
+#endif // JSON_WRITER_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsoncpp.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,4230 @@
+/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
+/// It is intented to be used with #include <json/json.h>
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+#define JSON_IS_AMALGAMATION
+
+
+#include <json/json.h>
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_tool.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+# define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+/* This header provides common string manipulation support, such as UTF-8,
+ * portable conversion from/to string...
+ *
+ * It is an internal header that must not be exposed.
+ */
+
+namespace Json {
+
+/// Converts a unicode code-point to UTF-8.
+static inline std::string 
+codePointToUTF8(unsigned int cp)
+{
+   std::string result;
+   
+   // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+   if (cp <= 0x7f) 
+   {
+      result.resize(1);
+      result[0] = static_cast<char>(cp);
+   } 
+   else if (cp <= 0x7FF) 
+   {
+      result.resize(2);
+      result[1] = static_cast<char>(0x80 | (0x3f & cp));
+      result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+   } 
+   else if (cp <= 0xFFFF) 
+   {
+      result.resize(3);
+      result[2] = static_cast<char>(0x80 | (0x3f & cp));
+      result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
+      result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
+   }
+   else if (cp <= 0x10FFFF) 
+   {
+      result.resize(4);
+      result[3] = static_cast<char>(0x80 | (0x3f & cp));
+      result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+      result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+      result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+   }
+
+   return result;
+}
+
+
+/// Returns true if ch is a control character (in range [0,32[).
+static inline bool 
+isControlCharacter(char ch)
+{
+   return ch > 0 && ch <= 0x1F;
+}
+
+
+enum { 
+   /// Constant that specify the size of the buffer that must be passed to uintToString.
+   uintToStringBufferSize = 3*sizeof(LargestUInt)+1 
+};
+
+// Defines a char buffer for use with uintToString().
+typedef char UIntToStringBuffer[uintToStringBufferSize];
+
+
+/** Converts an unsigned integer to string.
+ * @param value Unsigned interger to convert to string
+ * @param current Input/Output string buffer. 
+ *        Must have at least uintToStringBufferSize chars free.
+ */
+static inline void 
+uintToString( LargestUInt value, 
+              char *&current )
+{
+   *--current = 0;
+   do
+   {
+      *--current = char(value % 10) + '0';
+      value /= 10;
+   }
+   while ( value != 0 );
+}
+
+} // namespace Json {
+
+#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_tool.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_reader.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include <json/reader.h>
+# include <json/value.h>
+# include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+   : allowComments_( true )
+   , strictRoot_( false )
+{
+}
+
+
+Features 
+Features::all()
+{
+   return Features();
+}
+
+
+Features 
+Features::strictMode()
+{
+   Features features;
+   features.allowComments_ = false;
+   features.strictRoot_ = true;
+   return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4;
+}
+
+static inline bool 
+in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
+{
+   return c == c1  ||  c == c2  ||  c == c3  ||  c == c4  ||  c == c5;
+}
+
+
+static bool 
+containsNewLine( Reader::Location begin, 
+                 Reader::Location end )
+{
+   for ( ;begin < end; ++begin )
+      if ( *begin == '\n'  ||  *begin == '\r' )
+         return true;
+   return false;
+}
+
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+   : features_( Features::all() )
+{
+}
+
+
+Reader::Reader( const Features &features )
+   : features_( features )
+{
+}
+
+
+bool
+Reader::parse( const std::string &document, 
+               Value &root,
+               bool collectComments )
+{
+   document_ = document;
+   const char *begin = document_.c_str();
+   const char *end = begin + document_.length();
+   return parse( begin, end, root, collectComments );
+}
+
+
+bool
+Reader::parse( std::istream& sin,
+               Value &root,
+               bool collectComments )
+{
+   //std::istream_iterator<char> begin(sin);
+   //std::istream_iterator<char> end;
+   // Those would allow streamed input from a file, if parse() were a
+   // template function.
+
+   // Since std::string is reference-counted, this at least does not
+   // create an extra copy.
+   std::string doc;
+   std::getline(sin, doc, (char)EOF);
+   return parse( doc, root, collectComments );
+}
+
+bool 
+Reader::parse( const char *beginDoc, const char *endDoc, 
+               Value &root,
+               bool collectComments )
+{
+   if ( !features_.allowComments_ )
+   {
+      collectComments = false;
+   }
+
+   begin_ = beginDoc;
+   end_ = endDoc;
+   collectComments_ = collectComments;
+   current_ = begin_;
+   lastValueEnd_ = 0;
+   lastValue_ = 0;
+   commentsBefore_ = "";
+   errors_.clear();
+   while ( !nodes_.empty() )
+      nodes_.pop();
+   nodes_.push( &root );
+   
+   bool successful = readValue();
+   Token token;
+   skipCommentTokens( token );
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+      root.setComment( commentsBefore_, commentAfter );
+   if ( features_.strictRoot_ )
+   {
+      if ( !root.isArray()  &&  !root.isObject() )
+      {
+         // Set error location to start of doc, ideally should be first token found in doc
+         token.type_ = tokenError;
+         token.start_ = beginDoc;
+         token.end_ = endDoc;
+         addError( "A valid JSON document must be either an array or an object value.",
+                   token );
+         return false;
+      }
+   }
+   return successful;
+}
+
+
+bool
+Reader::readValue()
+{
+   Token token;
+   skipCommentTokens( token );
+   bool successful = true;
+
+   if ( collectComments_  &&  !commentsBefore_.empty() )
+   {
+      currentValue().setComment( commentsBefore_, commentBefore );
+      commentsBefore_ = "";
+   }
+
+
+   switch ( token.type_ )
+   {
+   case tokenObjectBegin:
+      successful = readObject( token );
+      break;
+   case tokenArrayBegin:
+      successful = readArray( token );
+      break;
+   case tokenNumber:
+      successful = decodeNumber( token );
+      break;
+   case tokenString:
+      successful = decodeString( token );
+      break;
+   case tokenTrue:
+      currentValue() = true;
+      break;
+   case tokenFalse:
+      currentValue() = false;
+      break;
+   case tokenNull:
+      currentValue() = Value();
+      break;
+   default:
+      return addError( "Syntax error: value, object or array expected.", token );
+   }
+
+   if ( collectComments_ )
+   {
+      lastValueEnd_ = current_;
+      lastValue_ = &currentValue();
+   }
+
+   return successful;
+}
+
+
+void 
+Reader::skipCommentTokens( Token &token )
+{
+   if ( features_.allowComments_ )
+   {
+      do
+      {
+         readToken( token );
+      }
+      while ( token.type_ == tokenComment );
+   }
+   else
+   {
+      readToken( token );
+   }
+}
+
+
+bool 
+Reader::expectToken( TokenType type, Token &token, const char *message )
+{
+   readToken( token );
+   if ( token.type_ != type )
+      return addError( message, token );
+   return true;
+}
+
+
+bool 
+Reader::readToken( Token &token )
+{
+   skipSpaces();
+   token.start_ = current_;
+   Char c = getNextChar();
+   bool ok = true;
+   switch ( c )
+   {
+   case '{':
+      token.type_ = tokenObjectBegin;
+      break;
+   case '}':
+      token.type_ = tokenObjectEnd;
+      break;
+   case '[':
+      token.type_ = tokenArrayBegin;
+      break;
+   case ']':
+      token.type_ = tokenArrayEnd;
+      break;
+   case '"':
+      token.type_ = tokenString;
+      ok = readString();
+      break;
+   case '/':
+      token.type_ = tokenComment;
+      ok = readComment();
+      break;
+   case '0':
+   case '1':
+   case '2':
+   case '3':
+   case '4':
+   case '5':
+   case '6':
+   case '7':
+   case '8':
+   case '9':
+   case '-':
+      token.type_ = tokenNumber;
+      readNumber();
+      break;
+   case 't':
+      token.type_ = tokenTrue;
+      ok = match( "rue", 3 );
+      break;
+   case 'f':
+      token.type_ = tokenFalse;
+      ok = match( "alse", 4 );
+      break;
+   case 'n':
+      token.type_ = tokenNull;
+      ok = match( "ull", 3 );
+      break;
+   case ',':
+      token.type_ = tokenArraySeparator;
+      break;
+   case ':':
+      token.type_ = tokenMemberSeparator;
+      break;
+   case 0:
+      token.type_ = tokenEndOfStream;
+      break;
+   default:
+      ok = false;
+      break;
+   }
+   if ( !ok )
+      token.type_ = tokenError;
+   token.end_ = current_;
+   return true;
+}
+
+
+void 
+Reader::skipSpaces()
+{
+   while ( current_ != end_ )
+   {
+      Char c = *current_;
+      if ( c == ' '  ||  c == '\t'  ||  c == '\r'  ||  c == '\n' )
+         ++current_;
+      else
+         break;
+   }
+}
+
+
+bool 
+Reader::match( Location pattern, 
+               int patternLength )
+{
+   if ( end_ - current_ < patternLength )
+      return false;
+   int index = patternLength;
+   while ( index-- )
+      if ( current_[index] != pattern[index] )
+         return false;
+   current_ += patternLength;
+   return true;
+}
+
+
+bool
+Reader::readComment()
+{
+   Location commentBegin = current_ - 1;
+   Char c = getNextChar();
+   bool successful = false;
+   if ( c == '*' )
+      successful = readCStyleComment();
+   else if ( c == '/' )
+      successful = readCppStyleComment();
+   if ( !successful )
+      return false;
+
+   if ( collectComments_ )
+   {
+      CommentPlacement placement = commentBefore;
+      if ( lastValueEnd_  &&  !containsNewLine( lastValueEnd_, commentBegin ) )
+      {
+         if ( c != '*'  ||  !containsNewLine( commentBegin, current_ ) )
+            placement = commentAfterOnSameLine;
+      }
+
+      addComment( commentBegin, current_, placement );
+   }
+   return true;
+}
+
+
+void 
+Reader::addComment( Location begin, 
+                    Location end, 
+                    CommentPlacement placement )
+{
+   assert( collectComments_ );
+   if ( placement == commentAfterOnSameLine )
+   {
+      assert( lastValue_ != 0 );
+      lastValue_->setComment( std::string( begin, end ), placement );
+   }
+   else
+   {
+      if ( !commentsBefore_.empty() )
+         commentsBefore_ += "\n";
+      commentsBefore_ += std::string( begin, end );
+   }
+}
+
+
+bool 
+Reader::readCStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if ( c == '*'  &&  *current_ == '/' )
+         break;
+   }
+   return getNextChar() == '/';
+}
+
+
+bool 
+Reader::readCppStyleComment()
+{
+   while ( current_ != end_ )
+   {
+      Char c = getNextChar();
+      if (  c == '\r'  ||  c == '\n' )
+         break;
+   }
+   return true;
+}
+
+
+void 
+Reader::readNumber()
+{
+   while ( current_ != end_ )
+   {
+      if ( !(*current_ >= '0'  &&  *current_ <= '9')  &&
+           !in( *current_, '.', 'e', 'E', '+', '-' ) )
+         break;
+      ++current_;
+   }
+}
+
+bool
+Reader::readString()
+{
+   Char c = 0;
+   while ( current_ != end_ )
+   {
+      c = getNextChar();
+      if ( c == '\\' )
+         getNextChar();
+      else if ( c == '"' )
+         break;
+   }
+   return c == '"';
+}
+
+
+bool 
+Reader::readObject( Token &/*tokenStart*/ )
+{
+   Token tokenName;
+   std::string name;
+   currentValue() = Value( objectValue );
+   while ( readToken( tokenName ) )
+   {
+      bool initialTokenOk = true;
+      while ( tokenName.type_ == tokenComment  &&  initialTokenOk )
+         initialTokenOk = readToken( tokenName );
+      if  ( !initialTokenOk )
+         break;
+      if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
+         return true;
+      if ( tokenName.type_ != tokenString )
+         break;
+      
+      name = "";
+      if ( !decodeString( tokenName, name ) )
+         return recoverFromError( tokenObjectEnd );
+
+      Token colon;
+      if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
+      {
+         return addErrorAndRecover( "Missing ':' after object member name", 
+                                    colon, 
+                                    tokenObjectEnd );
+      }
+      Value &value = currentValue()[ name ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenObjectEnd );
+
+      Token comma;
+      if ( !readToken( comma )
+            ||  ( comma.type_ != tokenObjectEnd  &&  
+                  comma.type_ != tokenArraySeparator &&
+                  comma.type_ != tokenComment ) )
+      {
+         return addErrorAndRecover( "Missing ',' or '}' in object declaration", 
+                                    comma, 
+                                    tokenObjectEnd );
+      }
+      bool finalizeTokenOk = true;
+      while ( comma.type_ == tokenComment &&
+              finalizeTokenOk )
+         finalizeTokenOk = readToken( comma );
+      if ( comma.type_ == tokenObjectEnd )
+         return true;
+   }
+   return addErrorAndRecover( "Missing '}' or object member name", 
+                              tokenName, 
+                              tokenObjectEnd );
+}
+
+
+bool 
+Reader::readArray( Token &/*tokenStart*/ )
+{
+   currentValue() = Value( arrayValue );
+   skipSpaces();
+   if ( *current_ == ']' ) // empty array
+   {
+      Token endArray;
+      readToken( endArray );
+      return true;
+   }
+   int index = 0;
+   for (;;)
+   {
+      Value &value = currentValue()[ index++ ];
+      nodes_.push( &value );
+      bool ok = readValue();
+      nodes_.pop();
+      if ( !ok ) // error already set
+         return recoverFromError( tokenArrayEnd );
+
+      Token token;
+      // Accept Comment after last item in the array.
+      ok = readToken( token );
+      while ( token.type_ == tokenComment  &&  ok )
+      {
+         ok = readToken( token );
+      }
+      bool badTokenType = ( token.type_ != tokenArraySeparator  &&
+                            token.type_ != tokenArrayEnd );
+      if ( !ok  ||  badTokenType )
+      {
+         return addErrorAndRecover( "Missing ',' or ']' in array declaration", 
+                                    token, 
+                                    tokenArrayEnd );
+      }
+      if ( token.type_ == tokenArrayEnd )
+         break;
+   }
+   return true;
+}
+
+
+bool 
+Reader::decodeNumber( Token &token )
+{
+   bool isDouble = false;
+   for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
+   {
+      isDouble = isDouble  
+                 ||  in( *inspect, '.', 'e', 'E', '+' )  
+                 ||  ( *inspect == '-'  &&  inspect != token.start_ );
+   }
+   if ( isDouble )
+      return decodeDouble( token );
+   // Attempts to parse the number as an integer. If the number is
+   // larger than the maximum supported value of an integer then
+   // we decode the number as a double.
+   Location current = token.start_;
+   bool isNegative = *current == '-';
+   if ( isNegative )
+      ++current;
+   Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) 
+                                                   : Value::maxLargestUInt;
+   Value::LargestUInt threshold = maxIntegerValue / 10;
+   Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 );
+   assert( lastDigitThreshold >=0  &&  lastDigitThreshold <= 9 );
+   Value::LargestUInt value = 0;
+   while ( current < token.end_ )
+   {
+      Char c = *current++;
+      if ( c < '0'  ||  c > '9' )
+         return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+      Value::UInt digit(c - '0');
+      if ( value >= threshold )
+      {
+         // If the current digit is not the last one, or if it is
+         // greater than the last digit of the maximum integer value,
+         // the parse the number as a double.
+         if ( current != token.end_  ||  digit > lastDigitThreshold )
+         {
+            return decodeDouble( token );
+         }
+      }
+      value = value * 10 + digit;
+   }
+   if ( isNegative )
+      currentValue() = -Value::LargestInt( value );
+   else if ( value <= Value::LargestUInt(Value::maxInt) )
+      currentValue() = Value::LargestInt( value );
+   else
+      currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeDouble( Token &token )
+{
+   double value = 0;
+   const int bufferSize = 32;
+   int count;
+   int length = int(token.end_ - token.start_);
+   if ( length <= bufferSize )
+   {
+      Char buffer[bufferSize+1];
+      memcpy( buffer, token.start_, length );
+      buffer[length] = 0;
+      count = sscanf( buffer, "%lf", &value );
+   }
+   else
+   {
+      std::string buffer( token.start_, token.end_ );
+      count = sscanf( buffer.c_str(), "%lf", &value );
+   }
+
+   if ( count != 1 )
+      return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
+   currentValue() = value;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token )
+{
+   std::string decoded;
+   if ( !decodeString( token, decoded ) )
+      return false;
+   currentValue() = decoded;
+   return true;
+}
+
+
+bool 
+Reader::decodeString( Token &token, std::string &decoded )
+{
+   decoded.reserve( token.end_ - token.start_ - 2 );
+   Location current = token.start_ + 1; // skip '"'
+   Location end = token.end_ - 1;      // do not include '"'
+   while ( current != end )
+   {
+      Char c = *current++;
+      if ( c == '"' )
+         break;
+      else if ( c == '\\' )
+      {
+         if ( current == end )
+            return addError( "Empty escape sequence in string", token, current );
+         Char escape = *current++;
+         switch ( escape )
+         {
+         case '"': decoded += '"'; break;
+         case '/': decoded += '/'; break;
+         case '\\': decoded += '\\'; break;
+         case 'b': decoded += '\b'; break;
+         case 'f': decoded += '\f'; break;
+         case 'n': decoded += '\n'; break;
+         case 'r': decoded += '\r'; break;
+         case 't': decoded += '\t'; break;
+         case 'u':
+            {
+               unsigned int unicode;
+               if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
+                  return false;
+               decoded += codePointToUTF8(unicode);
+            }
+            break;
+         default:
+            return addError( "Bad escape sequence in string", token, current );
+         }
+      }
+      else
+      {
+         decoded += c;
+      }
+   }
+   return true;
+}
+
+bool
+Reader::decodeUnicodeCodePoint( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+
+   if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
+      return false;
+   if (unicode >= 0xD800 && unicode <= 0xDBFF)
+   {
+      // surrogate pairs
+      if (end - current < 6)
+         return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
+      unsigned int surrogatePair;
+      if (*(current++) == '\\' && *(current++)== 'u')
+      {
+         if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
+         {
+            unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+         } 
+         else
+            return false;
+      } 
+      else
+         return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
+   }
+   return true;
+}
+
+bool 
+Reader::decodeUnicodeEscapeSequence( Token &token, 
+                                     Location &current, 
+                                     Location end, 
+                                     unsigned int &unicode )
+{
+   if ( end - current < 4 )
+      return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
+   unicode = 0;
+   for ( int index =0; index < 4; ++index )
+   {
+      Char c = *current++;
+      unicode *= 16;
+      if ( c >= '0'  &&  c <= '9' )
+         unicode += c - '0';
+      else if ( c >= 'a'  &&  c <= 'f' )
+         unicode += c - 'a' + 10;
+      else if ( c >= 'A'  &&  c <= 'F' )
+         unicode += c - 'A' + 10;
+      else
+         return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
+   }
+   return true;
+}
+
+
+bool 
+Reader::addError( const std::string &message, 
+                  Token &token,
+                  Location extra )
+{
+   ErrorInfo info;
+   info.token_ = token;
+   info.message_ = message;
+   info.extra_ = extra;
+   errors_.push_back( info );
+   return false;
+}
+
+
+bool 
+Reader::recoverFromError( TokenType skipUntilToken )
+{
+   int errorCount = int(errors_.size());
+   Token skip;
+   for (;;)
+   {
+      if ( !readToken(skip) )
+         errors_.resize( errorCount ); // discard errors caused by recovery
+      if ( skip.type_ == skipUntilToken  ||  skip.type_ == tokenEndOfStream )
+         break;
+   }
+   errors_.resize( errorCount );
+   return false;
+}
+
+
+bool 
+Reader::addErrorAndRecover( const std::string &message, 
+                            Token &token,
+                            TokenType skipUntilToken )
+{
+   addError( message, token );
+   return recoverFromError( skipUntilToken );
+}
+
+
+Value &
+Reader::currentValue()
+{
+   return *(nodes_.top());
+}
+
+
+Reader::Char 
+Reader::getNextChar()
+{
+   if ( current_ == end_ )
+      return 0;
+   return *current_++;
+}
+
+
+void 
+Reader::getLocationLineAndColumn( Location location,
+                                  int &line,
+                                  int &column ) const
+{
+   Location current = begin_;
+   Location lastLineStart = current;
+   line = 0;
+   while ( current < location  &&  current != end_ )
+   {
+      Char c = *current++;
+      if ( c == '\r' )
+      {
+         if ( *current == '\n' )
+            ++current;
+         lastLineStart = current;
+         ++line;
+      }
+      else if ( c == '\n' )
+      {
+         lastLineStart = current;
+         ++line;
+      }
+   }
+   // column & line start at 1
+   column = int(location - lastLineStart) + 1;
+   ++line;
+}
+
+
+std::string
+Reader::getLocationLineAndColumn( Location location ) const
+{
+   int line, column;
+   getLocationLineAndColumn( location, line, column );
+   char buffer[18+16+16+1];
+   sprintf( buffer, "Line %d, Column %d", line, column );
+   return buffer;
+}
+
+
+// Deprecated. Preserved for backward compatibility
+std::string 
+Reader::getFormatedErrorMessages() const
+{
+    return getFormattedErrorMessages();
+}
+
+
+std::string 
+Reader::getFormattedErrorMessages() const
+{
+   std::string formattedMessage;
+   for ( Errors::const_iterator itError = errors_.begin();
+         itError != errors_.end();
+         ++itError )
+   {
+      const ErrorInfo &error = *itError;
+      formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
+      formattedMessage += "  " + error.message_ + "\n";
+      if ( error.extra_ )
+         formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
+   }
+   return formattedMessage;
+}
+
+
+std::istream& operator>>( std::istream &sin, Value &root )
+{
+    Json::Reader reader;
+    bool ok = reader.parse(sin, root, true);
+    //JSON_ASSERT( ok );
+    if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages());
+    return sin;
+}
+
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_reader.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_batchallocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
+# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+# include <stdlib.h>
+# include <assert.h>
+
+# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+namespace Json {
+
+/* Fast memory allocator.
+ *
+ * This memory allocator allocates memory for a batch of object (specified by
+ * the page size, the number of object in each page).
+ *
+ * It does not allow the destruction of a single object. All the allocated objects
+ * can be destroyed at once. The memory can be either released or reused for future
+ * allocation.
+ * 
+ * The in-place new operator must be used to construct the object using the pointer
+ * returned by allocate.
+ */
+template<typename AllocatedType
+        ,const unsigned int objectPerAllocation>
+class BatchAllocator
+{
+public:
+   typedef AllocatedType Type;
+
+   BatchAllocator( unsigned int objectsPerPage = 255 )
+      : freeHead_( 0 )
+      , objectsPerPage_( objectsPerPage )
+   {
+//      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
+      assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
+      assert( objectsPerPage >= 16 );
+      batches_ = allocateBatch( 0 );   // allocated a dummy page
+      currentBatch_ = batches_;
+   }
+
+   ~BatchAllocator()
+   {
+      for ( BatchInfo *batch = batches_; batch;  )
+      {
+         BatchInfo *nextBatch = batch->next_;
+         free( batch );
+         batch = nextBatch;
+      }
+   }
+
+   /// allocate space for an array of objectPerAllocation object.
+   /// @warning it is the responsability of the caller to call objects constructors.
+   AllocatedType *allocate()
+   {
+      if ( freeHead_ ) // returns node from free list.
+      {
+         AllocatedType *object = freeHead_;
+         freeHead_ = *(AllocatedType **)object;
+         return object;
+      }
+      if ( currentBatch_->used_ == currentBatch_->end_ )
+      {
+         currentBatch_ = currentBatch_->next_;
+         while ( currentBatch_  &&  currentBatch_->used_ == currentBatch_->end_ )
+            currentBatch_ = currentBatch_->next_;
+
+         if ( !currentBatch_  ) // no free batch found, allocate a new one
+         { 
+            currentBatch_ = allocateBatch( objectsPerPage_ );
+            currentBatch_->next_ = batches_; // insert at the head of the list
+            batches_ = currentBatch_;
+         }
+      }
+      AllocatedType *allocated = currentBatch_->used_;
+      currentBatch_->used_ += objectPerAllocation;
+      return allocated;
+   }
+
+   /// Release the object.
+   /// @warning it is the responsability of the caller to actually destruct the object.
+   void release( AllocatedType *object )
+   {
+      assert( object != 0 );
+      *(AllocatedType **)object = freeHead_;
+      freeHead_ = object;
+   }
+
+private:
+   struct BatchInfo
+   {
+      BatchInfo *next_;
+      AllocatedType *used_;
+      AllocatedType *end_;
+      AllocatedType buffer_[objectPerAllocation];
+   };
+
+   // disabled copy constructor and assignement operator.
+   BatchAllocator( const BatchAllocator & );
+   void operator =( const BatchAllocator &);
+
+   static BatchInfo *allocateBatch( unsigned int objectsPerPage )
+   {
+      const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+                                + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
+      BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
+      batch->next_ = 0;
+      batch->used_ = batch->buffer_;
+      batch->end_ = batch->buffer_ + objectsPerPage;
+      return batch;
+   }
+
+   BatchInfo *batches_;
+   BatchInfo *currentBatch_;
+   /// Head of a single linked list within the allocated space of freeed object
+   AllocatedType *freeHead_;
+   unsigned int objectsPerPage_;
+};
+
+
+} // namespace Json
+
+# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
+
+#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
+
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_batchallocator.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_valueiterator.inl
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+// included by json_value.cpp
+
+namespace Json {
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   : current_()
+   , isNull_( true )
+{
+}
+#else
+   : isArray_( true )
+   , isNull_( true )
+{
+   iterator_.array_ = ValueInternalArray::IteratorState();
+}
+#endif
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
+   : current_( current )
+   , isNull_( false )
+{
+}
+#else
+ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
+   : isArray_( true )
+{
+   iterator_.array_ = state;
+}
+
+
+ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
+   : isArray_( false )
+{
+   iterator_.map_ = state;
+}
+#endif
+
+Value &
+ValueIteratorBase::deref() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   return current_->second;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::dereference( iterator_.array_ );
+   return ValueInternalMap::value( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::increment()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ++current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::increment( iterator_.array_ );
+   ValueInternalMap::increment( iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::decrement()
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   --current_;
+#else
+   if ( isArray_ )
+      ValueInternalArray::decrement( iterator_.array_ );
+   ValueInternalMap::decrement( iterator_.map_ );
+#endif
+}
+
+
+ValueIteratorBase::difference_type 
+ValueIteratorBase::computeDistance( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+# ifdef JSON_USE_CPPTL_SMALLMAP
+   return current_ - other.current_;
+# else
+   // Iterator for null value are initialized using the default
+   // constructor, which initialize current_ to the default
+   // std::map::iterator. As begin() and end() are two instance 
+   // of the default std::map::iterator, they can not be compared.
+   // To allow this, we handle this comparison specifically.
+   if ( isNull_  &&  other.isNull_ )
+   {
+      return 0;
+   }
+
+
+   // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
+   // which is the one used by default).
+   // Using a portable hand-made version for non random iterator instead:
+   //   return difference_type( std::distance( current_, other.current_ ) );
+   difference_type myDistance = 0;
+   for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
+   {
+      ++myDistance;
+   }
+   return myDistance;
+# endif
+#else
+   if ( isArray_ )
+      return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+bool 
+ValueIteratorBase::isEqual( const SelfType &other ) const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   if ( isNull_ )
+   {
+      return other.isNull_;
+   }
+   return current_ == other.current_;
+#else
+   if ( isArray_ )
+      return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
+   return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
+#endif
+}
+
+
+void 
+ValueIteratorBase::copy( const SelfType &other )
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   current_ = other.current_;
+#else
+   if ( isArray_ )
+      iterator_.array_ = other.iterator_.array_;
+   iterator_.map_ = other.iterator_.map_;
+#endif
+}
+
+
+Value 
+ValueIteratorBase::key() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( czstring.c_str() )
+   {
+      if ( czstring.isStaticString() )
+         return Value( StaticString( czstring.c_str() ) );
+      return Value( czstring.c_str() );
+   }
+   return Value( czstring.index() );
+#else
+   if ( isArray_ )
+      return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
+   bool isStatic;
+   const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
+   if ( isStatic )
+      return Value( StaticString( memberName ) );
+   return Value( memberName );
+#endif
+}
+
+
+UInt 
+ValueIteratorBase::index() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const Value::CZString czstring = (*current_).first;
+   if ( !czstring.c_str() )
+      return czstring.index();
+   return Value::UInt( -1 );
+#else
+   if ( isArray_ )
+      return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
+   return Value::UInt( -1 );
+#endif
+}
+
+
+const char *
+ValueIteratorBase::memberName() const
+{
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   const char *name = (*current_).first.c_str();
+   return name ? name : "";
+#else
+   if ( !isArray_ )
+      return ValueInternalMap::key( iterator_.map_ );
+   return "";
+#endif
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueConstIterator &
+ValueConstIterator::operator =( const ValueIteratorBase &other )
+{
+   copy( other );
+   return *this;
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator()
+{
+}
+
+
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
+   : ValueIteratorBase( current )
+{
+}
+#else
+ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+
+ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
+   : ValueIteratorBase( state )
+{
+}
+#endif
+
+ValueIterator::ValueIterator( const ValueConstIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator::ValueIterator( const ValueIterator &other )
+   : ValueIteratorBase( other )
+{
+}
+
+ValueIterator &
+ValueIterator::operator =( const SelfType &other )
+{
+   copy( other );
+   return *this;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_valueiterator.inl
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_value.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include <json/value.h>
+# include <json/writer.h>
+# ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+#  include "json_batchallocator.h"
+# endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <iostream>
+#include <utility>
+#include <stdexcept>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+# include <cpptl/conststring.h>
+#endif
+#include <cstddef>    // size_t
+
+#define JSON_ASSERT_UNREACHABLE assert( false )
+#define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
+#define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message );
+#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message )
+
+namespace Json {
+
+const Value Value::null;
+const Int Value::minInt = Int( ~(UInt(-1)/2) );
+const Int Value::maxInt = Int( UInt(-1)/2 );
+const UInt Value::maxUInt = UInt(-1);
+const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
+const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
+const UInt64 Value::maxUInt64 = UInt64(-1);
+const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
+const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
+const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+
+
+/// Unknown size marker
+static const unsigned int unknown = (unsigned)-1;
+
+
+/** Duplicates the specified string value.
+ * @param value Pointer to the string to duplicate. Must be zero-terminated if
+ *              length is "unknown".
+ * @param length Length of the value. if equals to unknown, then it will be
+ *               computed using strlen(value).
+ * @return Pointer on the duplicate instance of string.
+ */
+static inline char *
+duplicateStringValue( const char *value, 
+                      unsigned int length = unknown )
+{
+   if ( length == unknown )
+      length = (unsigned int)strlen(value);
+   char *newString = static_cast<char *>( malloc( length + 1 ) );
+   JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" );
+   memcpy( newString, value, length );
+   newString[length] = 0;
+   return newString;
+}
+
+
+/** Free the string duplicated by duplicateStringValue().
+ */
+static inline void 
+releaseStringValue( char *value )
+{
+   if ( value )
+      free( value );
+}
+
+} // namespace Json
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#if !defined(JSON_IS_AMALGAMATION)
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+#  include "json_internalarray.inl"
+#  include "json_internalmap.inl"
+# endif // JSON_VALUE_USE_INTERNAL_MAP
+
+# include "json_valueiterator.inl"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+Value::CommentInfo::CommentInfo()
+   : comment_( 0 )
+{
+}
+
+Value::CommentInfo::~CommentInfo()
+{
+   if ( comment_ )
+      releaseStringValue( comment_ );
+}
+
+
+void 
+Value::CommentInfo::setComment( const char *text )
+{
+   if ( comment_ )
+      releaseStringValue( comment_ );
+   JSON_ASSERT( text != 0 );
+   JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
+   // It seems that /**/ style comments are acceptable as well.
+   comment_ = duplicateStringValue( text );
+}
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+# ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+// Notes: index_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString( ArrayIndex index )
+   : cstr_( 0 )
+   , index_( index )
+{
+}
+
+Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
+   : cstr_( allocate == duplicate ? duplicateStringValue(cstr) 
+                                  : cstr )
+   , index_( allocate )
+{
+}
+
+Value::CZString::CZString( const CZString &other )
+: cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
+                ?  duplicateStringValue( other.cstr_ )
+                : other.cstr_ )
+   , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
+                         : other.index_ )
+{
+}
+
+Value::CZString::~CZString()
+{
+   if ( cstr_  &&  index_ == duplicate )
+      releaseStringValue( const_cast<char *>( cstr_ ) );
+}
+
+void 
+Value::CZString::swap( CZString &other )
+{
+   std::swap( cstr_, other.cstr_ );
+   std::swap( index_, other.index_ );
+}
+
+Value::CZString &
+Value::CZString::operator =( const CZString &other )
+{
+   CZString temp( other );
+   swap( temp );
+   return *this;
+}
+
+bool 
+Value::CZString::operator<( const CZString &other ) const 
+{
+   if ( cstr_ )
+      return strcmp( cstr_, other.cstr_ ) < 0;
+   return index_ < other.index_;
+}
+
+bool 
+Value::CZString::operator==( const CZString &other ) const 
+{
+   if ( cstr_ )
+      return strcmp( cstr_, other.cstr_ ) == 0;
+   return index_ == other.index_;
+}
+
+
+ArrayIndex 
+Value::CZString::index() const
+{
+   return index_;
+}
+
+
+const char *
+Value::CZString::c_str() const
+{
+   return cstr_;
+}
+
+bool 
+Value::CZString::isStaticString() const
+{
+   return index_ == noDuplication;
+}
+
+#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value( ValueType type )
+   : type_( type )
+   , allocated_( 0 )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   switch ( type )
+   {
+   case nullValue:
+      break;
+   case intValue:
+   case uintValue:
+      value_.int_ = 0;
+      break;
+   case realValue:
+      value_.real_ = 0.0;
+      break;
+   case stringValue:
+      value_.string_ = 0;
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_ = new ObjectValues();
+      break;
+#else
+   case arrayValue:
+      value_.array_ = arrayAllocator()->newArray();
+      break;
+   case objectValue:
+      value_.map_ = mapAllocator()->newMap();
+      break;
+#endif
+   case booleanValue:
+      value_.bool_ = false;
+      break;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+}
+
+
+#if defined(JSON_HAS_INT64)
+Value::Value( UInt value )
+   : type_( uintValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.uint_ = value;
+}
+
+Value::Value( Int value )
+   : type_( intValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.int_ = value;
+}
+
+#endif // if defined(JSON_HAS_INT64)
+
+
+Value::Value( Int64 value )
+   : type_( intValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.int_ = value;
+}
+
+
+Value::Value( UInt64 value )
+   : type_( uintValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.uint_ = value;
+}
+
+Value::Value( double value )
+   : type_( realValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.real_ = value;
+}
+
+Value::Value( const char *value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = duplicateStringValue( value );
+}
+
+
+Value::Value( const char *beginValue, 
+              const char *endValue )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = duplicateStringValue( beginValue, 
+                                          (unsigned int)(endValue - beginValue) );
+}
+
+
+Value::Value( const std::string &value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = duplicateStringValue( value.c_str(), 
+                                          (unsigned int)value.length() );
+
+}
+
+Value::Value( const StaticString &value )
+   : type_( stringValue )
+   , allocated_( false )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = const_cast<char *>( value.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value::Value( const CppTL::ConstString &value )
+   : type_( stringValue )
+   , allocated_( true )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.string_ = duplicateStringValue( value, value.length() );
+}
+# endif
+
+Value::Value( bool value )
+   : type_( booleanValue )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   value_.bool_ = value;
+}
+
+
+Value::Value( const Value &other )
+   : type_( other.type_ )
+   , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+   , itemIsUsed_( 0 )
+#endif
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      value_ = other.value_;
+      break;
+   case stringValue:
+      if ( other.value_.string_ )
+      {
+         value_.string_ = duplicateStringValue( other.value_.string_ );
+         allocated_ = true;
+      }
+      else
+         value_.string_ = 0;
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_ = new ObjectValues( *other.value_.map_ );
+      break;
+#else
+   case arrayValue:
+      value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
+      break;
+   case objectValue:
+      value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
+      break;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   if ( other.comments_ )
+   {
+      comments_ = new CommentInfo[numberOfCommentPlacement];
+      for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
+      {
+         const CommentInfo &otherComment = other.comments_[comment];
+         if ( otherComment.comment_ )
+            comments_[comment].setComment( otherComment.comment_ );
+      }
+   }
+}
+
+
+Value::~Value()
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+      break;
+   case stringValue:
+      if ( allocated_ )
+         releaseStringValue( value_.string_ );
+      break;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      delete value_.map_;
+      break;
+#else
+   case arrayValue:
+      arrayAllocator()->destructArray( value_.array_ );
+      break;
+   case objectValue:
+      mapAllocator()->destructMap( value_.map_ );
+      break;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+
+   if ( comments_ )
+      delete[] comments_;
+}
+
+Value &
+Value::operator=( const Value &other )
+{
+   Value temp( other );
+   swap( temp );
+   return *this;
+}
+
+void 
+Value::swap( Value &other )
+{
+   ValueType temp = type_;
+   type_ = other.type_;
+   other.type_ = temp;
+   std::swap( value_, other.value_ );
+   int temp2 = allocated_;
+   allocated_ = other.allocated_;
+   other.allocated_ = temp2;
+}
+
+ValueType 
+Value::type() const
+{
+   return type_;
+}
+
+
+int 
+Value::compare( const Value &other ) const
+{
+   if ( *this < other )
+      return -1;
+   if ( *this > other )
+      return 1;
+   return 0;
+}
+
+
+bool 
+Value::operator <( const Value &other ) const
+{
+   int typeDelta = type_ - other.type_;
+   if ( typeDelta )
+      return typeDelta < 0 ? true : false;
+   switch ( type_ )
+   {
+   case nullValue:
+      return false;
+   case intValue:
+      return value_.int_ < other.value_.int_;
+   case uintValue:
+      return value_.uint_ < other.value_.uint_;
+   case realValue:
+      return value_.real_ < other.value_.real_;
+   case booleanValue:
+      return value_.bool_ < other.value_.bool_;
+   case stringValue:
+      return ( value_.string_ == 0  &&  other.value_.string_ )
+             || ( other.value_.string_  
+                  &&  value_.string_  
+                  && strcmp( value_.string_, other.value_.string_ ) < 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      {
+         int delta = int( value_.map_->size() - other.value_.map_->size() );
+         if ( delta )
+            return delta < 0;
+         return (*value_.map_) < (*other.value_.map_);
+      }
+#else
+   case arrayValue:
+      return value_.array_->compare( *(other.value_.array_) ) < 0;
+   case objectValue:
+      return value_.map_->compare( *(other.value_.map_) ) < 0;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false;  // unreachable
+}
+
+bool 
+Value::operator <=( const Value &other ) const
+{
+   return !(other < *this);
+}
+
+bool 
+Value::operator >=( const Value &other ) const
+{
+   return !(*this < other);
+}
+
+bool 
+Value::operator >( const Value &other ) const
+{
+   return other < *this;
+}
+
+bool 
+Value::operator ==( const Value &other ) const
+{
+   //if ( type_ != other.type_ )
+   // GCC 2.95.3 says:
+   // attempt to take address of bit-field structure member `Json::Value::type_'
+   // Beats me, but a temp solves the problem.
+   int temp = other.type_;
+   if ( type_ != temp )
+      return false;
+   switch ( type_ )
+   {
+   case nullValue:
+      return true;
+   case intValue:
+      return value_.int_ == other.value_.int_;
+   case uintValue:
+      return value_.uint_ == other.value_.uint_;
+   case realValue:
+      return value_.real_ == other.value_.real_;
+   case booleanValue:
+      return value_.bool_ == other.value_.bool_;
+   case stringValue:
+      return ( value_.string_ == other.value_.string_ )
+             || ( other.value_.string_  
+                  &&  value_.string_  
+                  && strcmp( value_.string_, other.value_.string_ ) == 0 );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      return value_.map_->size() == other.value_.map_->size()
+             && (*value_.map_) == (*other.value_.map_);
+#else
+   case arrayValue:
+      return value_.array_->compare( *(other.value_.array_) ) == 0;
+   case objectValue:
+      return value_.map_->compare( *(other.value_.map_) ) == 0;
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false;  // unreachable
+}
+
+bool 
+Value::operator !=( const Value &other ) const
+{
+   return !( *this == other );
+}
+
+const char *
+Value::asCString() const
+{
+   JSON_ASSERT( type_ == stringValue );
+   return value_.string_;
+}
+
+
+std::string 
+Value::asString() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return "";
+   case stringValue:
+      return value_.string_ ? value_.string_ : "";
+   case booleanValue:
+      return value_.bool_ ? "true" : "false";
+   case intValue:
+   case uintValue:
+   case realValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to string" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return ""; // unreachable
+}
+
+# ifdef JSON_USE_CPPTL
+CppTL::ConstString 
+Value::asConstString() const
+{
+   return CppTL::ConstString( asString().c_str() );
+}
+# endif
+
+
+Value::Int 
+Value::asInt() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      JSON_ASSERT_MESSAGE( value_.int_ >= minInt  &&  value_.int_ <= maxInt, "unsigned integer out of signed int range" );
+      return Int(value_.int_);
+   case uintValue:
+      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
+      return Int(value_.uint_);
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
+      return Int( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to int" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+Value::UInt 
+Value::asUInt() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
+      JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" );
+      return UInt(value_.int_);
+   case uintValue:
+      JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" );
+      return UInt(value_.uint_);
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
+      return UInt( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to uint" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+# if defined(JSON_HAS_INT64)
+
+Value::Int64
+Value::asInt64() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      return value_.int_;
+   case uintValue:
+      JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" );
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= minInt64  &&  value_.real_ <= maxInt64, "Real out of Int64 range" );
+      return Int( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to Int64" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+Value::UInt64
+Value::asUInt64() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0;
+   case intValue:
+      JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" );
+      return value_.int_;
+   case uintValue:
+      return value_.uint_;
+   case realValue:
+      JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt64,  "Real out of UInt64 range" );
+      return UInt( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1 : 0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+# endif // if defined(JSON_HAS_INT64)
+
+
+LargestInt 
+Value::asLargestInt() const
+{
+#if defined(JSON_NO_INT64)
+    return asInt();
+#else
+    return asInt64();
+#endif
+}
+
+
+LargestUInt 
+Value::asLargestUInt() const
+{
+#if defined(JSON_NO_INT64)
+    return asUInt();
+#else
+    return asUInt64();
+#endif
+}
+
+
+double 
+Value::asDouble() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0.0;
+   case intValue:
+      return static_cast<double>( value_.int_ );
+   case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+      return static_cast<double>( value_.uint_ );
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+      return static_cast<double>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+   case realValue:
+      return value_.real_;
+   case booleanValue:
+      return value_.bool_ ? 1.0 : 0.0;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to double" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+float
+Value::asFloat() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return 0.0f;
+   case intValue:
+      return static_cast<float>( value_.int_ );
+   case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+      return static_cast<float>( value_.uint_ );
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+      return static_cast<float>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+   case realValue:
+      return static_cast<float>( value_.real_ );
+   case booleanValue:
+      return value_.bool_ ? 1.0f : 0.0f;
+   case stringValue:
+   case arrayValue:
+   case objectValue:
+      JSON_FAIL_MESSAGE( "Type is not convertible to float" );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0.0f; // unreachable;
+}
+
+bool 
+Value::asBool() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return false;
+   case intValue:
+   case uintValue:
+      return value_.int_ != 0;
+   case realValue:
+      return value_.real_ != 0.0;
+   case booleanValue:
+      return value_.bool_;
+   case stringValue:
+      return value_.string_  &&  value_.string_[0] != 0;
+   case arrayValue:
+   case objectValue:
+      return value_.map_->size() != 0;
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false; // unreachable;
+}
+
+
+bool 
+Value::isConvertibleTo( ValueType other ) const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+      return true;
+   case intValue:
+      return ( other == nullValue  &&  value_.int_ == 0 )
+             || other == intValue
+             || ( other == uintValue  && value_.int_ >= 0 )
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case uintValue:
+      return ( other == nullValue  &&  value_.uint_ == 0 )
+             || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
+             || other == uintValue
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case realValue:
+      return ( other == nullValue  &&  value_.real_ == 0.0 )
+             || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
+             || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case booleanValue:
+      return ( other == nullValue  &&  value_.bool_ == false )
+             || other == intValue
+             || other == uintValue
+             || other == realValue
+             || other == stringValue
+             || other == booleanValue;
+   case stringValue:
+      return other == stringValue
+             || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
+   case arrayValue:
+      return other == arrayValue
+             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
+   case objectValue:
+      return other == objectValue
+             ||  ( other == nullValue  &&  value_.map_->size() == 0 );
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return false; // unreachable;
+}
+
+
+/// Number of values in array or object
+ArrayIndex 
+Value::size() const
+{
+   switch ( type_ )
+   {
+   case nullValue:
+   case intValue:
+   case uintValue:
+   case realValue:
+   case booleanValue:
+   case stringValue:
+      return 0;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:  // size of the array is highest index + 1
+      if ( !value_.map_->empty() )
+      {
+         ObjectValues::const_iterator itLast = value_.map_->end();
+         --itLast;
+         return (*itLast).first.index()+1;
+      }
+      return 0;
+   case objectValue:
+      return ArrayIndex( value_.map_->size() );
+#else
+   case arrayValue:
+      return Int( value_.array_->size() );
+   case objectValue:
+      return Int( value_.map_->size() );
+#endif
+   default:
+      JSON_ASSERT_UNREACHABLE;
+   }
+   return 0; // unreachable;
+}
+
+
+bool 
+Value::empty() const
+{
+   if ( isNull() || isArray() || isObject() )
+      return size() == 0u;
+   else
+      return false;
+}
+
+
+bool
+Value::operator!() const
+{
+   return isNull();
+}
+
+
+void 
+Value::clear()
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
+
+   switch ( type_ )
+   {
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+   case objectValue:
+      value_.map_->clear();
+      break;
+#else
+   case arrayValue:
+      value_.array_->clear();
+      break;
+   case objectValue:
+      value_.map_->clear();
+      break;
+#endif
+   default:
+      break;
+   }
+}
+
+void 
+Value::resize( ArrayIndex newSize )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ArrayIndex oldSize = size();
+   if ( newSize == 0 )
+      clear();
+   else if ( newSize > oldSize )
+      (*this)[ newSize - 1 ];
+   else
+   {
+      for ( ArrayIndex index = newSize; index < oldSize; ++index )
+      {
+         value_.map_->erase( index );
+      }
+      assert( size() == newSize );
+   }
+#else
+   value_.array_->resize( newSize );
+#endif
+}
+
+
+Value &
+Value::operator[]( ArrayIndex index )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      *this = Value( arrayValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString key( index );
+   ObjectValues::iterator it = value_.map_->lower_bound( key );
+   if ( it != value_.map_->end()  &&  (*it).first == key )
+      return (*it).second;
+
+   ObjectValues::value_type defaultValue( key, null );
+   it = value_.map_->insert( it, defaultValue );
+   return (*it).second;
+#else
+   return value_.array_->resolveReference( index );
+#endif
+}
+
+
+Value &
+Value::operator[]( int index )
+{
+   JSON_ASSERT( index >= 0 );
+   return (*this)[ ArrayIndex(index) ];
+}
+
+
+const Value &
+Value::operator[]( ArrayIndex index ) const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString key( index );
+   ObjectValues::const_iterator it = value_.map_->find( key );
+   if ( it == value_.map_->end() )
+      return null;
+   return (*it).second;
+#else
+   Value *value = value_.array_->find( index );
+   return value ? *value : null;
+#endif
+}
+
+
+const Value &
+Value::operator[]( int index ) const
+{
+   JSON_ASSERT( index >= 0 );
+   return (*this)[ ArrayIndex(index) ];
+}
+
+
+Value &
+Value::operator[]( const char *key )
+{
+   return resolveReference( key, false );
+}
+
+
+Value &
+Value::resolveReference( const char *key, 
+                         bool isStatic )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      *this = Value( objectValue );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, isStatic ? CZString::noDuplication 
+                                     : CZString::duplicateOnCopy );
+   ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
+   if ( it != value_.map_->end()  &&  (*it).first == actualKey )
+      return (*it).second;
+
+   ObjectValues::value_type defaultValue( actualKey, null );
+   it = value_.map_->insert( it, defaultValue );
+   Value &value = (*it).second;
+   return value;
+#else
+   return value_.map_->resolveReference( key, isStatic );
+#endif
+}
+
+
+Value 
+Value::get( ArrayIndex index, 
+            const Value &defaultValue ) const
+{
+   const Value *value = &((*this)[index]);
+   return value == &null ? defaultValue : *value;
+}
+
+
+bool 
+Value::isValidIndex( ArrayIndex index ) const
+{
+   return index < size();
+}
+
+
+
+const Value &
+Value::operator[]( const char *key ) const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, CZString::noDuplication );
+   ObjectValues::const_iterator it = value_.map_->find( actualKey );
+   if ( it == value_.map_->end() )
+      return null;
+   return (*it).second;
+#else
+   const Value *value = value_.map_->find( key );
+   return value ? *value : null;
+#endif
+}
+
+
+Value &
+Value::operator[]( const std::string &key )
+{
+   return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const std::string &key ) const
+{
+   return (*this)[ key.c_str() ];
+}
+
+Value &
+Value::operator[]( const StaticString &key )
+{
+   return resolveReference( key, true );
+}
+
+
+# ifdef JSON_USE_CPPTL
+Value &
+Value::operator[]( const CppTL::ConstString &key )
+{
+   return (*this)[ key.c_str() ];
+}
+
+
+const Value &
+Value::operator[]( const CppTL::ConstString &key ) const
+{
+   return (*this)[ key.c_str() ];
+}
+# endif
+
+
+Value &
+Value::append( const Value &value )
+{
+   return (*this)[size()] = value;
+}
+
+
+Value 
+Value::get( const char *key, 
+            const Value &defaultValue ) const
+{
+   const Value *value = &((*this)[key]);
+   return value == &null ? defaultValue : *value;
+}
+
+
+Value 
+Value::get( const std::string &key,
+            const Value &defaultValue ) const
+{
+   return get( key.c_str(), defaultValue );
+}
+
+Value
+Value::removeMember( const char* key )
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+      return null;
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   CZString actualKey( key, CZString::noDuplication );
+   ObjectValues::iterator it = value_.map_->find( actualKey );
+   if ( it == value_.map_->end() )
+      return null;
+   Value old(it->second);
+   value_.map_->erase(it);
+   return old;
+#else
+   Value *value = value_.map_->find( key );
+   if (value){
+      Value old(*value);
+      value_.map_.remove( key );
+      return old;
+   } else {
+      return null;
+   }
+#endif
+}
+
+Value
+Value::removeMember( const std::string &key )
+{
+   return removeMember( key.c_str() );
+}
+
+# ifdef JSON_USE_CPPTL
+Value 
+Value::get( const CppTL::ConstString &key,
+            const Value &defaultValue ) const
+{
+   return get( key.c_str(), defaultValue );
+}
+# endif
+
+bool 
+Value::isMember( const char *key ) const
+{
+   const Value *value = &((*this)[key]);
+   return value != &null;
+}
+
+
+bool 
+Value::isMember( const std::string &key ) const
+{
+   return isMember( key.c_str() );
+}
+
+
+# ifdef JSON_USE_CPPTL
+bool 
+Value::isMember( const CppTL::ConstString &key ) const
+{
+   return isMember( key.c_str() );
+}
+#endif
+
+Value::Members 
+Value::getMemberNames() const
+{
+   JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
+   if ( type_ == nullValue )
+       return Value::Members();
+   Members members;
+   members.reserve( value_.map_->size() );
+#ifndef JSON_VALUE_USE_INTERNAL_MAP
+   ObjectValues::const_iterator it = value_.map_->begin();
+   ObjectValues::const_iterator itEnd = value_.map_->end();
+   for ( ; it != itEnd; ++it )
+      members.push_back( std::string( (*it).first.c_str() ) );
+#else
+   ValueInternalMap::IteratorState it;
+   ValueInternalMap::IteratorState itEnd;
+   value_.map_->makeBeginIterator( it );
+   value_.map_->makeEndIterator( itEnd );
+   for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
+      members.push_back( std::string( ValueInternalMap::key( it ) ) );
+#endif
+   return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+//EnumMemberNames
+//Value::enumMemberNames() const
+//{
+//   if ( type_ == objectValue )
+//   {
+//      return CppTL::Enum::any(  CppTL::Enum::transform(
+//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+//         MemberNamesTransform() ) );
+//   }
+//   return EnumMemberNames();
+//}
+//
+//
+//EnumValues 
+//Value::enumValues() const
+//{
+//   if ( type_ == objectValue  ||  type_ == arrayValue )
+//      return CppTL::Enum::anyValues( *(value_.map_), 
+//                                     CppTL::Type<const Value &>() );
+//   return EnumValues();
+//}
+//
+//# endif
+
+
+bool
+Value::isNull() const
+{
+   return type_ == nullValue;
+}
+
+
+bool 
+Value::isBool() const
+{
+   return type_ == booleanValue;
+}
+
+
+bool 
+Value::isInt() const
+{
+   return type_ == intValue;
+}
+
+
+bool 
+Value::isUInt() const
+{
+   return type_ == uintValue;
+}
+
+
+bool 
+Value::isIntegral() const
+{
+   return type_ == intValue  
+          ||  type_ == uintValue  
+          ||  type_ == booleanValue;
+}
+
+
+bool 
+Value::isDouble() const
+{
+   return type_ == realValue;
+}
+
+
+bool 
+Value::isNumeric() const
+{
+   return isIntegral() || isDouble();
+}
+
+
+bool 
+Value::isString() const
+{
+   return type_ == stringValue;
+}
+
+
+bool 
+Value::isArray() const
+{
+   return type_ == nullValue  ||  type_ == arrayValue;
+}
+
+
+bool 
+Value::isObject() const
+{
+   return type_ == nullValue  ||  type_ == objectValue;
+}
+
+
+void 
+Value::setComment( const char *comment,
+                   CommentPlacement placement )
+{
+   if ( !comments_ )
+      comments_ = new CommentInfo[numberOfCommentPlacement];
+   comments_[placement].setComment( comment );
+}
+
+
+void 
+Value::setComment( const std::string &comment,
+                   CommentPlacement placement )
+{
+   setComment( comment.c_str(), placement );
+}
+
+
+bool 
+Value::hasComment( CommentPlacement placement ) const
+{
+   return comments_ != 0  &&  comments_[placement].comment_ != 0;
+}
+
+std::string 
+Value::getComment( CommentPlacement placement ) const
+{
+   if ( hasComment(placement) )
+      return comments_[placement].comment_;
+   return "";
+}
+
+
+std::string 
+Value::toStyledString() const
+{
+   StyledWriter writer;
+   return writer.write( *this );
+}
+
+
+Value::const_iterator 
+Value::begin() const
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeBeginIterator( it );
+         return const_iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeBeginIterator( it );
+         return const_iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return const_iterator( value_.map_->begin() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return const_iterator();
+}
+
+Value::const_iterator 
+Value::end() const
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeEndIterator( it );
+         return const_iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeEndIterator( it );
+         return const_iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return const_iterator( value_.map_->end() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return const_iterator();
+}
+
+
+Value::iterator 
+Value::begin()
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeBeginIterator( it );
+         return iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeBeginIterator( it );
+         return iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return iterator( value_.map_->begin() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return iterator();
+}
+
+Value::iterator 
+Value::end()
+{
+   switch ( type_ )
+   {
+#ifdef JSON_VALUE_USE_INTERNAL_MAP
+   case arrayValue:
+      if ( value_.array_ )
+      {
+         ValueInternalArray::IteratorState it;
+         value_.array_->makeEndIterator( it );
+         return iterator( it );
+      }
+      break;
+   case objectValue:
+      if ( value_.map_ )
+      {
+         ValueInternalMap::IteratorState it;
+         value_.map_->makeEndIterator( it );
+         return iterator( it );
+      }
+      break;
+#else
+   case arrayValue:
+   case objectValue:
+      if ( value_.map_ )
+         return iterator( value_.map_->end() );
+      break;
+#endif
+   default:
+      break;
+   }
+   return iterator();
+}
+
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument()
+   : kind_( kindNone )
+{
+}
+
+
+PathArgument::PathArgument( ArrayIndex index )
+   : index_( index )
+   , kind_( kindIndex )
+{
+}
+
+
+PathArgument::PathArgument( const char *key )
+   : key_( key )
+   , kind_( kindKey )
+{
+}
+
+
+PathArgument::PathArgument( const std::string &key )
+   : key_( key.c_str() )
+   , kind_( kindKey )
+{
+}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path( const std::string &path,
+            const PathArgument &a1,
+            const PathArgument &a2,
+            const PathArgument &a3,
+            const PathArgument &a4,
+            const PathArgument &a5 )
+{
+   InArgs in;
+   in.push_back( &a1 );
+   in.push_back( &a2 );
+   in.push_back( &a3 );
+   in.push_back( &a4 );
+   in.push_back( &a5 );
+   makePath( path, in );
+}
+
+
+void 
+Path::makePath( const std::string &path,
+                const InArgs &in )
+{
+   const char *current = path.c_str();
+   const char *end = current + path.length();
+   InArgs::const_iterator itInArg = in.begin();
+   while ( current != end )
+   {
+      if ( *current == '[' )
+      {
+         ++current;
+         if ( *current == '%' )
+            addPathInArg( path, in, itInArg, PathArgument::kindIndex );
+         else
+         {
+            ArrayIndex index = 0;
+            for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
+               index = index * 10 + ArrayIndex(*current - '0');
+            args_.push_back( index );
+         }
+         if ( current == end  ||  *current++ != ']' )
+            invalidPath( path, int(current - path.c_str()) );
+      }
+      else if ( *current == '%' )
+      {
+         addPathInArg( path, in, itInArg, PathArgument::kindKey );
+         ++current;
+      }
+      else if ( *current == '.' )
+      {
+         ++current;
+      }
+      else
+      {
+         const char *beginName = current;
+         while ( current != end  &&  !strchr( "[.", *current ) )
+            ++current;
+         args_.push_back( std::string( beginName, current ) );
+      }
+   }
+}
+
+
+void 
+Path::addPathInArg( const std::string &path, 
+                    const InArgs &in, 
+                    InArgs::const_iterator &itInArg, 
+                    PathArgument::Kind kind )
+{
+   if ( itInArg == in.end() )
+   {
+      // Error: missing argument %d
+   }
+   else if ( (*itInArg)->kind_ != kind )
+   {
+      // Error: bad argument type
+   }
+   else
+   {
+      args_.push_back( **itInArg );
+   }
+}
+
+
+void 
+Path::invalidPath( const std::string &path, 
+                   int location )
+{
+   // Error: invalid path.
+}
+
+
+const Value &
+Path::resolve( const Value &root ) const
+{
+   const Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
+         {
+            // Error: unable to resolve path (array value expected at position...
+         }
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+         {
+            // Error: unable to resolve path (object value expected at position...)
+         }
+         node = &((*node)[arg.key_]);
+         if ( node == &Value::null )
+         {
+            // Error: unable to resolve path (object has no member named '' at position...)
+         }
+      }
+   }
+   return *node;
+}
+
+
+Value 
+Path::resolve( const Value &root, 
+               const Value &defaultValue ) const
+{
+   const Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
+            return defaultValue;
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+            return defaultValue;
+         node = &((*node)[arg.key_]);
+         if ( node == &Value::null )
+            return defaultValue;
+      }
+   }
+   return *node;
+}
+
+
+Value &
+Path::make( Value &root ) const
+{
+   Value *node = &root;
+   for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
+   {
+      const PathArgument &arg = *it;
+      if ( arg.kind_ == PathArgument::kindIndex )
+      {
+         if ( !node->isArray() )
+         {
+            // Error: node is not an array at position ...
+         }
+         node = &((*node)[arg.index_]);
+      }
+      else if ( arg.kind_ == PathArgument::kindKey )
+      {
+         if ( !node->isObject() )
+         {
+            // Error: node is not an object at position...
+         }
+         node = &((*node)[arg.key_]);
+      }
+   }
+   return *node;
+}
+
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_value.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_writer.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+# include <json/writer.h>
+# include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <utility>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+
+#if _MSC_VER >= 1400 // VC++ 8.0
+#pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
+#endif
+
+namespace Json {
+
+static bool containsControlCharacter( const char* str )
+{
+   while ( *str ) 
+   {
+      if ( isControlCharacter( *(str++) ) )
+         return true;
+   }
+   return false;
+}
+
+
+std::string valueToString( LargestInt value )
+{
+   UIntToStringBuffer buffer;
+   char *current = buffer + sizeof(buffer);
+   bool isNegative = value < 0;
+   if ( isNegative )
+      value = -value;
+   uintToString( LargestUInt(value), current );
+   if ( isNegative )
+      *--current = '-';
+   assert( current >= buffer );
+   return current;
+}
+
+
+std::string valueToString( LargestUInt value )
+{
+   UIntToStringBuffer buffer;
+   char *current = buffer + sizeof(buffer);
+   uintToString( value, current );
+   assert( current >= buffer );
+   return current;
+}
+
+#if defined(JSON_HAS_INT64)
+
+std::string valueToString( Int value )
+{
+   return valueToString( LargestInt(value) );
+}
+
+
+std::string valueToString( UInt value )
+{
+   return valueToString( LargestUInt(value) );
+}
+
+#endif // # if defined(JSON_HAS_INT64)
+
+
+std::string valueToString( double value )
+{
+   char buffer[32];
+#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. 
+   sprintf_s(buffer, sizeof(buffer), "%#.16g", value); 
+#else	
+   sprintf(buffer, "%#.16g", value); 
+#endif
+   char* ch = buffer + strlen(buffer) - 1;
+   if (*ch != '0') return buffer; // nothing to truncate, so save time
+   while(ch > buffer && *ch == '0'){
+     --ch;
+   }
+   char* last_nonzero = ch;
+   while(ch >= buffer){
+     switch(*ch){
+     case '0':
+     case '1':
+     case '2':
+     case '3':
+     case '4':
+     case '5':
+     case '6':
+     case '7':
+     case '8':
+     case '9':
+       --ch;
+       continue;
+     case '.':
+       // Truncate zeroes to save bytes in output, but keep one.
+       *(last_nonzero+2) = '\0';
+       return buffer;
+     default:
+       return buffer;
+     }
+   }
+   return buffer;
+}
+
+
+std::string valueToString( bool value )
+{
+   return value ? "true" : "false";
+}
+
+std::string valueToQuotedString( const char *value )
+{
+   // Not sure how to handle unicode...
+   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
+      return std::string("\"") + value + "\"";
+   // We have to walk value and escape any special characters.
+   // Appending to std::string is not efficient, but this should be rare.
+   // (Note: forward slashes are *not* rare, but I am not escaping them.)
+   std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
+   std::string result;
+   result.reserve(maxsize); // to avoid lots of mallocs
+   result += "\"";
+   for (const char* c=value; *c != 0; ++c)
+   {
+      switch(*c)
+      {
+         case '\"':
+            result += "\\\"";
+            break;
+         case '\\':
+            result += "\\\\";
+            break;
+         case '\b':
+            result += "\\b";
+            break;
+         case '\f':
+            result += "\\f";
+            break;
+         case '\n':
+            result += "\\n";
+            break;
+         case '\r':
+            result += "\\r";
+            break;
+         case '\t':
+            result += "\\t";
+            break;
+         //case '/':
+            // Even though \/ is considered a legal escape in JSON, a bare
+            // slash is also legal, so I see no reason to escape it.
+            // (I hope I am not misunderstanding something.
+            // blep notes: actually escaping \/ may be useful in javascript to avoid </ 
+            // sequence.
+            // Should add a flag to allow this compatibility mode and prevent this 
+            // sequence from occurring.
+         default:
+            if ( isControlCharacter( *c ) )
+            {
+               std::ostringstream oss;
+               oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
+               result += oss.str();
+            }
+            else
+            {
+               result += *c;
+            }
+            break;
+      }
+   }
+   result += "\"";
+   return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer()
+{
+}
+
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+   : yamlCompatiblityEnabled_( false )
+{
+}
+
+
+void 
+FastWriter::enableYAMLCompatibility()
+{
+   yamlCompatiblityEnabled_ = true;
+}
+
+
+std::string 
+FastWriter::write( const Value &root )
+{
+   document_ = "";
+   writeValue( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+FastWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      document_ += "null";
+      break;
+   case intValue:
+      document_ += valueToString( value.asLargestInt() );
+      break;
+   case uintValue:
+      document_ += valueToString( value.asLargestUInt() );
+      break;
+   case realValue:
+      document_ += valueToString( value.asDouble() );
+      break;
+   case stringValue:
+      document_ += valueToQuotedString( value.asCString() );
+      break;
+   case booleanValue:
+      document_ += valueToString( value.asBool() );
+      break;
+   case arrayValue:
+      {
+         document_ += "[";
+         int size = value.size();
+         for ( int index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ",";
+            writeValue( value[index] );
+         }
+         document_ += "]";
+      }
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         document_ += "{";
+         for ( Value::Members::iterator it = members.begin(); 
+               it != members.end(); 
+               ++it )
+         {
+            const std::string &name = *it;
+            if ( it != members.begin() )
+               document_ += ",";
+            document_ += valueToQuotedString( name.c_str() );
+            document_ += yamlCompatiblityEnabled_ ? ": " 
+                                                  : ":";
+            writeValue( value[name] );
+         }
+         document_ += "}";
+      }
+      break;
+   }
+}
+
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+   : rightMargin_( 74 )
+   , indentSize_( 3 )
+{
+}
+
+
+std::string 
+StyledWriter::write( const Value &root )
+{
+   document_ = "";
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   document_ += "\n";
+   return document_;
+}
+
+
+void 
+StyledWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asLargestInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asLargestUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            for (;;)
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               document_ += " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               document_ += ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         for (;;)
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+               writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            document_ += ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         document_ += "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               document_ += ", ";
+            document_ += childValues_[index];
+         }
+         document_ += " ]";
+      }
+   }
+}
+
+
+bool 
+StyledWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      document_ += value;
+}
+
+
+void 
+StyledWriter::writeIndent()
+{
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         document_ += '\n';
+   }
+   document_ += indentString_;
+}
+
+
+void 
+StyledWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   document_ += value;
+}
+
+
+void 
+StyledWriter::indent()
+{
+   indentString_ += std::string( indentSize_, ' ' );
+}
+
+
+void 
+StyledWriter::unindent()
+{
+   assert( int(indentString_.size()) >= indentSize_ );
+   indentString_.resize( indentString_.size() - indentSize_ );
+}
+
+
+void 
+StyledWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   document_ += normalizeEOL( root.getComment( commentBefore ) );
+   document_ += "\n";
+}
+
+
+void 
+StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      document_ += "\n";
+      document_ += normalizeEOL( root.getComment( commentAfter ) );
+      document_ += "\n";
+   }
+}
+
+
+bool 
+StyledWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter( std::string indentation )
+   : document_(NULL)
+   , rightMargin_( 74 )
+   , indentation_( indentation )
+{
+}
+
+
+void
+StyledStreamWriter::write( std::ostream &out, const Value &root )
+{
+   document_ = &out;
+   addChildValues_ = false;
+   indentString_ = "";
+   writeCommentBeforeValue( root );
+   writeValue( root );
+   writeCommentAfterValueOnSameLine( root );
+   *document_ << "\n";
+   document_ = NULL; // Forget the stream, for safety.
+}
+
+
+void 
+StyledStreamWriter::writeValue( const Value &value )
+{
+   switch ( value.type() )
+   {
+   case nullValue:
+      pushValue( "null" );
+      break;
+   case intValue:
+      pushValue( valueToString( value.asLargestInt() ) );
+      break;
+   case uintValue:
+      pushValue( valueToString( value.asLargestUInt() ) );
+      break;
+   case realValue:
+      pushValue( valueToString( value.asDouble() ) );
+      break;
+   case stringValue:
+      pushValue( valueToQuotedString( value.asCString() ) );
+      break;
+   case booleanValue:
+      pushValue( valueToString( value.asBool() ) );
+      break;
+   case arrayValue:
+      writeArrayValue( value);
+      break;
+   case objectValue:
+      {
+         Value::Members members( value.getMemberNames() );
+         if ( members.empty() )
+            pushValue( "{}" );
+         else
+         {
+            writeWithIndent( "{" );
+            indent();
+            Value::Members::iterator it = members.begin();
+            for (;;)
+            {
+               const std::string &name = *it;
+               const Value &childValue = value[name];
+               writeCommentBeforeValue( childValue );
+               writeWithIndent( valueToQuotedString( name.c_str() ) );
+               *document_ << " : ";
+               writeValue( childValue );
+               if ( ++it == members.end() )
+               {
+                  writeCommentAfterValueOnSameLine( childValue );
+                  break;
+               }
+               *document_ << ",";
+               writeCommentAfterValueOnSameLine( childValue );
+            }
+            unindent();
+            writeWithIndent( "}" );
+         }
+      }
+      break;
+   }
+}
+
+
+void 
+StyledStreamWriter::writeArrayValue( const Value &value )
+{
+   unsigned size = value.size();
+   if ( size == 0 )
+      pushValue( "[]" );
+   else
+   {
+      bool isArrayMultiLine = isMultineArray( value );
+      if ( isArrayMultiLine )
+      {
+         writeWithIndent( "[" );
+         indent();
+         bool hasChildValue = !childValues_.empty();
+         unsigned index =0;
+         for (;;)
+         {
+            const Value &childValue = value[index];
+            writeCommentBeforeValue( childValue );
+            if ( hasChildValue )
+               writeWithIndent( childValues_[index] );
+            else
+            {
+               writeIndent();
+               writeValue( childValue );
+            }
+            if ( ++index == size )
+            {
+               writeCommentAfterValueOnSameLine( childValue );
+               break;
+            }
+            *document_ << ",";
+            writeCommentAfterValueOnSameLine( childValue );
+         }
+         unindent();
+         writeWithIndent( "]" );
+      }
+      else // output on a single line
+      {
+         assert( childValues_.size() == size );
+         *document_ << "[ ";
+         for ( unsigned index =0; index < size; ++index )
+         {
+            if ( index > 0 )
+               *document_ << ", ";
+            *document_ << childValues_[index];
+         }
+         *document_ << " ]";
+      }
+   }
+}
+
+
+bool 
+StyledStreamWriter::isMultineArray( const Value &value )
+{
+   int size = value.size();
+   bool isMultiLine = size*3 >= rightMargin_ ;
+   childValues_.clear();
+   for ( int index =0; index < size  &&  !isMultiLine; ++index )
+   {
+      const Value &childValue = value[index];
+      isMultiLine = isMultiLine  ||
+                     ( (childValue.isArray()  ||  childValue.isObject())  &&  
+                        childValue.size() > 0 );
+   }
+   if ( !isMultiLine ) // check if line length > max line length
+   {
+      childValues_.reserve( size );
+      addChildValues_ = true;
+      int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
+      for ( int index =0; index < size  &&  !isMultiLine; ++index )
+      {
+         writeValue( value[index] );
+         lineLength += int( childValues_[index].length() );
+         isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
+      }
+      addChildValues_ = false;
+      isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
+   }
+   return isMultiLine;
+}
+
+
+void 
+StyledStreamWriter::pushValue( const std::string &value )
+{
+   if ( addChildValues_ )
+      childValues_.push_back( value );
+   else
+      *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::writeIndent()
+{
+  /*
+    Some comments in this method would have been nice. ;-)
+
+   if ( !document_.empty() )
+   {
+      char last = document_[document_.length()-1];
+      if ( last == ' ' )     // already indented
+         return;
+      if ( last != '\n' )    // Comments may add new-line
+         *document_ << '\n';
+   }
+  */
+   *document_ << '\n' << indentString_;
+}
+
+
+void 
+StyledStreamWriter::writeWithIndent( const std::string &value )
+{
+   writeIndent();
+   *document_ << value;
+}
+
+
+void 
+StyledStreamWriter::indent()
+{
+   indentString_ += indentation_;
+}
+
+
+void 
+StyledStreamWriter::unindent()
+{
+   assert( indentString_.size() >= indentation_.size() );
+   indentString_.resize( indentString_.size() - indentation_.size() );
+}
+
+
+void 
+StyledStreamWriter::writeCommentBeforeValue( const Value &root )
+{
+   if ( !root.hasComment( commentBefore ) )
+      return;
+   *document_ << normalizeEOL( root.getComment( commentBefore ) );
+   *document_ << "\n";
+}
+
+
+void 
+StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
+{
+   if ( root.hasComment( commentAfterOnSameLine ) )
+      *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
+
+   if ( root.hasComment( commentAfter ) )
+   {
+      *document_ << "\n";
+      *document_ << normalizeEOL( root.getComment( commentAfter ) );
+      *document_ << "\n";
+   }
+}
+
+
+bool 
+StyledStreamWriter::hasCommentForValue( const Value &value )
+{
+   return value.hasComment( commentBefore )
+          ||  value.hasComment( commentAfterOnSameLine )
+          ||  value.hasComment( commentAfter );
+}
+
+
+std::string 
+StyledStreamWriter::normalizeEOL( const std::string &text )
+{
+   std::string normalized;
+   normalized.reserve( text.length() );
+   const char *begin = text.c_str();
+   const char *end = begin + text.length();
+   const char *current = begin;
+   while ( current != end )
+   {
+      char c = *current++;
+      if ( c == '\r' ) // mac or dos EOL
+      {
+         if ( *current == '\n' ) // convert dos EOL
+            ++current;
+         normalized += '\n';
+      }
+      else // handle unix EOL & other char
+         normalized += c;
+   }
+   return normalized;
+}
+
+
+std::ostream& operator<<( std::ostream &sout, const Value &root )
+{
+   Json::StyledStreamWriter writer;
+   writer.write(sout, root);
+   return sout;
+}
+
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_writer.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,19 @@
+#include "ofMain.h"
+
+#include "ofAppiOSWindow.h"
+#include "testApp.h"
+
+int main(){
+    ofAppiOSWindow * window = new ofAppiOSWindow();
+    window->enableHardwareOrientation();
+    window->enableOrientationAnimation();
+    window->enableAntiAliasing(4);
+	window->enableRetina();
+    
+    ofSeedRandom();
+    
+	ofSetupOpenGL(window, 768, 1024,OF_FULLSCREEN);
+	ofRunApp(new testApp);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pd patch/targetSynth7.pd	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,2006 @@
+#N canvas 406 189 1013 774 10;
+#X obj 109 189 dac~;
+#X obj 100 162 +~;
+#X obj 133 163 +~;
+#X text 180 159 to do swap between with short fade to prevent reverb
+mixing up;
+#X text 278 110 to do: remove sine osc or make it FM and do something
+clever;
+#X obj 136 -68 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 313 -71 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 206 -267 r fromOF;
+#X obj 200 -237 route list;
+#X obj 153 -128 route candidateSynth;
+#X obj 286 -128 route targetSynth;
+#N canvas 0 22 450 300 alternator 0;
+#X obj 126 64 inlet;
+#X obj 65 234 outlet;
+#X obj 245 232 outlet;
+#X text 39 23 sends bangs to alternate outlets at certain interval
+;
+#X obj 126 119 metro 1000;
+#X obj 181 64 inlet;
+#X text 121 46 on off;
+#X obj 181 91 * 2;
+#X obj 244 188 delay 500;
+#X connect 0 0 4 0;
+#X connect 4 0 1 0;
+#X connect 4 0 8 0;
+#X connect 5 0 7 0;
+#X connect 5 0 8 1;
+#X connect 7 0 4 1;
+#X connect 8 0 2 0;
+#X restore 449 -111 pd alternator;
+#X obj 448 -148 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1
+1 1;
+#X obj 523 -157 loadbang;
+#X obj 523 -133 int 500;
+#X obj 446 -182 route startAlternator;
+#X obj 467 -232 loadbang;
+#X obj 288 -99 route playSound;
+#X obj 141 -93 route playSound;
+#X obj 468 -207 int 0;
+#N canvas 830 119 910 816 candidateSynth 0;
+#X obj 83 467 outlet~;
+#X obj 143 466 outlet~;
+#X obj 659 -257 inlet;
+#X obj 181 -294 inlet;
+#X obj 96 296 *~;
+#X obj 73 375 clip~ -1 1;
+#X obj 664 -65 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 80 56 / 127;
+#X obj 119 57 / 127;
+#X text 81 -112 attack;
+#X text 124 -112 decay;
+#X text -53 -112 pitch;
+#X text -7 -114 duration;
+#X obj 258 49 / 127;
+#X text 299 -115 ftype;
+#X text 342 -115 ffreq;
+#X text 464 -117 reson;
+#X text 562 -111 reverb;
+#X obj 92 335 *~ 0.1;
+#X text 35 -102 wavef;
+#X text 655 -95 trigger;
+#X obj -38 -168 route pitch;
+#X obj 44 -169 route waveform;
+#X obj 138 -169 route attack;
+#X obj 221 -171 route decay;
+#X obj 301 -170 route fType;
+#X obj 378 -167 route fFreq;
+#X obj 459 -169 route reson;
+#X obj 547 -172 route reverb;
+#N canvas 42 77 1074 773 filterT 0;
+#X obj 44 22 inlet~;
+#X obj 165 84 route filtFreq;
+#X obj 855 112 route reson;
+#X obj 99 639 outlet~;
+#X obj 169 306 mtof~;
+#X obj 167 43 route list;
+#X obj 165 11 r fromOF;
+#X obj 316 19 inlet~;
+#X text 362 19 envelope;
+#X obj 171 189 sig~;
+#X obj 174 250 +~;
+#X obj 662 265 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 565 230 filetr freq;
+#X text 645 226 resonance;
+#X floatatom 822 416 5 0 0 0 - - -;
+#X msg 363 391 \$1 100;
+#X obj 363 415 line~;
+#X obj 407 303 hsl 128 15 0 1 0 1 empty empty empty -2 -8 0 10 -262144
+-1 -1 5600 1;
+#X text 284 273 Mode: 0 = lowpass \, 0.5 = resonant bandpass \, 1 =
+highpass;
+#X floatatom 403 356 5 0 0 0 - - -;
+#X obj 820 472 + 100;
+#X obj 820 496 dbtorms;
+#X floatatom 820 525 5 0 0 0 - - -;
+#X obj 820 443 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262144 -1 -1 3 256;
+#X obj 364 149 route fType;
+#X obj 820 356 / 5;
+#X obj 98 558 multimode_libpd.mmb~;
+#X obj 99 598 biquad_libpd.mmb~;
+#X floatatom 659 420 5 0 0 0 - - -;
+#X obj 167 280 clip~ 20 128;
+#X obj 169 220 lop~ 50;
+#X obj 169 122 * 0.6;
+#X obj 172 158 + 30;
+#X obj 238 221 *~ 110;
+#X obj 882 28 r fromOF;
+#X obj 815 553 lop~ 50;
+#X obj 881 57 route list;
+#X obj 891 81 route smoothing;
+#X text 38 2 audio in;
+#X text 478 17 ftype;
+#X text 590 17 ffreq;
+#X obj 544 17 inlet;
+#X obj 432 17 inlet;
+#X obj 646 17 inlet;
+#X text 692 17 reson;
+#X floatatom 195 386 5 0 0 0 - - -;
+#X obj 820 389 + 3;
+#X connect 0 0 27 0;
+#X connect 1 0 31 0;
+#X connect 2 0 25 0;
+#X connect 4 0 26 0;
+#X connect 5 0 1 0;
+#X connect 5 0 2 0;
+#X connect 5 0 24 0;
+#X connect 6 0 5 0;
+#X connect 7 0 33 0;
+#X connect 9 0 30 0;
+#X connect 10 0 29 0;
+#X connect 11 0 25 0;
+#X connect 11 0 28 0;
+#X connect 14 0 23 0;
+#X connect 15 0 16 0;
+#X connect 16 0 26 2;
+#X connect 17 0 19 0;
+#X connect 17 0 15 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 35 0;
+#X connect 23 0 20 0;
+#X connect 24 0 15 0;
+#X connect 25 0 46 0;
+#X connect 26 0 27 1;
+#X connect 26 1 27 2;
+#X connect 26 2 27 3;
+#X connect 26 3 27 4;
+#X connect 26 4 27 5;
+#X connect 27 0 3 0;
+#X connect 29 0 4 0;
+#X connect 30 0 10 0;
+#X connect 31 0 32 0;
+#X connect 32 0 9 0;
+#X connect 33 0 10 1;
+#X connect 34 0 36 0;
+#X connect 35 0 26 1;
+#X connect 36 0 37 0;
+#X connect 37 0 35 1;
+#X connect 37 0 30 1;
+#X connect 41 0 31 0;
+#X connect 42 0 15 0;
+#X connect 43 0 25 0;
+#X connect 46 0 14 0;
+#X restore 77 250 pd filterT;
+#X obj 92 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 120 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 1400 1;
+#X obj 268 -93 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 346 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 7600 1;
+#X obj 457 -94 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 565 -75 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#N canvas 76 137 871 723 oscillatorC 0;
+#X obj 83 269 phasor~;
+#X obj 430 -51 inlet;
+#X text 73 522 audio out;
+#X obj 79 501 outlet~;
+#X obj 402 171 mtof;
+#X text 292 -112 "pWidth" \, "sqVol" \, "sawVol" \, "sineVol" \, "FMAmt"
+;
+#X obj 321 233 +~;
+#X obj 402 193 sig~;
+#X floatatom 564 131 5 0 0 0 - - -;
+#X text 627 93 fm rfeq;
+#X obj 353 113 loadbang;
+#X obj 262 398 osc~ 220;
+#X text 29 390 subtract out of phase one;
+#X obj 84 377 -~;
+#X obj 151 327 wrap~;
+#X obj 150 302 +~ 0.5;
+#X obj 83 437 -~ 0.5;
+#X obj 568 186 *~ 0;
+#X obj 562 156 osc~;
+#X obj 561 105 mtof;
+#X obj 731 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 723 64 / 127;
+#X obj 548 29 * 100;
+#X obj 765 -85 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 764 62 / 127;
+#X obj 152 354 *~ 0;
+#X obj 263 429 *~ 1;
+#X obj 616 129 * 3500;
+#X obj 559 81 +;
+#X obj 560 54 - 40;
+#X text 408 -73 pitch freq;
+#X obj 552 1 route FMFreq FMAmt;
+#X obj 564 218 lop~ 20;
+#X obj 680 172 r fromOF;
+#X obj 679 201 route list;
+#X obj 677 226 route smoothing;
+#X obj 84 346 *~ 1;
+#X obj 66 124 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 16 122 inlet;
+#X text 52 93 waveform;
+#X floatatom 42 198 5 0 0 0 - - -;
+#X floatatom 93 201 5 0 0 0 - - -;
+#X floatatom 141 205 5 0 0 0 - - -;
+#X floatatom 190 203 5 0 0 0 - - -;
+#X obj 29 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 101 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 170 -14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 31 19 float 10;
+#X obj 103 19 float 64;
+#X obj 173 21 float 120;
+#X text 192 219 sineVol;
+#X text 30 218 saw vol;
+#X text 92 221 sq vol;
+#N canvas 71 22 1849 1017 interpolatorWave 0;
+#X obj 80 -91 inlet;
+#X text 75 -113 slider control;
+#X obj 217 74 < 32;
+#X obj 202 100 &&;
+#X floatatom 211 122 5 0 0 0 - - -;
+#X obj 186 74 >= 0;
+#X obj 279 99 &&;
+#X obj 359 98 &&;
+#X obj 444 97 &&;
+#X obj 263 73 >= 32;
+#X obj 300 73 < 64;
+#X obj 339 73 >= 64;
+#X obj 380 72 < 96;
+#X obj 428 71 >= 96;
+#X obj 465 71 < 128;
+#X floatatom 273 121 5 0 0 0 - - -;
+#X floatatom 354 119 5 0 0 0 - - -;
+#X floatatom 438 118 5 0 0 0 - - -;
+#X obj 273 148 * 2;
+#X obj 355 147 * 3;
+#X obj 436 147 * 4;
+#X obj 246 205 +;
+#X obj 398 200 +;
+#X obj 315 246 +;
+#X floatatom 105 352 5 0 0 0 - - -;
+#X floatatom 181 356 5 0 0 0 - - -;
+#X floatatom 246 356 5 0 0 0 - - -;
+#X floatatom 316 352 5 0 0 0 - - -;
+#X obj -125 824 outlet;
+#X obj 116 408 / 32;
+#X obj 181 408 / 32;
+#X obj 243 410 / 32;
+#X obj 316 408 / 32;
+#X obj 177 381 - 32;
+#X obj 245 382 - 64;
+#X obj 317 378 - 96;
+#X text 544 477 calc frac;
+#X obj 35 498 -;
+#X obj 35 479 float 1;
+#X obj 159 626 loadbang;
+#X obj -134 764 + 0;
+#X floatatom 85 526 5 0 0 0 - - -;
+#X floatatom 36 527 5 0 0 0 - - -;
+#X obj -150 736 * 0.1;
+#X obj -113 736 * 0.15;
+#X obj -42 760 + 0;
+#X obj -58 732 * 0.1;
+#X obj -21 732 * 0.15;
+#X obj 45 761 + 0;
+#X obj 138 762 + 0;
+#X obj 153 506 -;
+#X obj 153 487 float 1;
+#X floatatom 200 526 5 0 0 0 - - -;
+#X floatatom 154 528 5 0 0 0 - - -;
+#X obj 286 502 -;
+#X obj 286 483 float 1;
+#X floatatom 335 526 5 0 0 0 - - -;
+#X floatatom 287 524 5 0 0 0 - - -;
+#X text 6 678 insert values at points here;
+#X obj 416 505 -;
+#X obj 416 486 float 1;
+#X floatatom 467 526 5 0 0 0 - - -;
+#X floatatom 417 527 5 0 0 0 - - -;
+#X obj 29 733 * 30;
+#X obj 66 733 * 60;
+#X obj 119 733 * 60;
+#X obj 159 734 * 90;
+#X obj -543 849 outlet;
+#X obj -557 676 loadbang;
+#X obj -552 789 + 0;
+#X obj -568 761 * 0.1;
+#X obj -531 761 * 0.15;
+#X obj -460 785 + 0;
+#X obj -476 757 * 0.1;
+#X obj -439 757 * 0.15;
+#X obj -373 786 + 0;
+#X obj -280 787 + 0;
+#X text -630 702 insert values at points here;
+#X obj -389 758 * 30;
+#X obj -352 758 * 60;
+#X obj -299 758 * 60;
+#X obj -259 759 * 90;
+#X text -541 827 comment;
+#X obj -543 728 float 0;
+#X obj -262 725 float 1;
+#X text -595 848 saw vol;
+#X text -207 825 pulse volume;
+#X obj -470 726 float 0;
+#X obj -402 728 float 1;
+#X obj -330 726 float 1;
+#X obj -125 703 float 0;
+#X obj -52 701 float 0;
+#X obj 16 703 float 0;
+#X obj 88 701 float 1;
+#X obj 157 701 float 1;
+#X obj 264 818 outlet;
+#X obj 548 620 loadbang;
+#X obj 255 758 + 0;
+#X obj 239 730 * 0.1;
+#X obj 276 730 * 0.15;
+#X obj 347 754 + 0;
+#X obj 331 726 * 0.1;
+#X obj 368 726 * 0.15;
+#X obj 434 755 + 0;
+#X obj 527 756 + 0;
+#X text 373 667 insert values at points here;
+#X obj 418 727 * 30;
+#X obj 455 727 * 60;
+#X obj 508 727 * 60;
+#X obj 548 728 * 90;
+#X text 182 819 pulse width;
+#X obj 677 819 outlet;
+#X obj 961 621 loadbang;
+#X obj 668 759 + 0;
+#X obj 652 731 * 0.1;
+#X obj 689 731 * 0.15;
+#X obj 760 755 + 0;
+#X obj 744 727 * 0.1;
+#X obj 781 727 * 0.15;
+#X obj 847 756 + 0;
+#X obj 940 757 + 0;
+#X text 682 664 insert values at points here;
+#X obj 831 728 * 30;
+#X obj 868 728 * 60;
+#X obj 921 728 * 60;
+#X obj 961 729 * 90;
+#X obj 397 174 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 315 224 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 246 175 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 255 28 t f f f f f f f f;
+#X obj 117 -57 t f f;
+#X obj 415 462 t b f f;
+#X obj 283 458 t b f f;
+#X obj 155 463 t b f f;
+#X obj 36 452 t b f f;
+#X text 266 796 comment;
+#X text -124 801 comment;
+#X obj 959 696 float 0;
+#X text 595 820 sine volume;
+#X obj 677 698 float 1;
+#X obj 750 696 float 1;
+#X obj 818 698 float 0;
+#X obj 891 696 float 0;
+#X obj 477 695 float 0.5;
+#X obj 405 697 float 0.5;
+#X obj 337 695 float 0.5;
+#X obj 264 697 float 0.5;
+#X obj 166 308 route 1 2 3 4;
+#X obj 164 281 pack;
+#X obj 546 695 float 0.01;
+#X obj 1061 811 outlet;
+#X obj 1345 613 loadbang;
+#X obj 1052 751 + 0;
+#X obj 1036 723 * 0.1;
+#X obj 1073 723 * 0.15;
+#X obj 1144 747 + 0;
+#X obj 1124 720 * 0.1;
+#X obj 1165 719 * 0.15;
+#X obj 1231 748 + 0;
+#X obj 1324 749 + 0;
+#X text 1066 656 insert values at points here;
+#X obj 1215 720 * 30;
+#X obj 1252 720 * 60;
+#X obj 1305 720 * 60;
+#X obj 1345 721 * 90;
+#X obj 1343 688 float 0;
+#X obj 1275 688 float 0;
+#X text 979 812 FM Freq;
+#X obj 1492 672 outlet;
+#X obj 1776 474 loadbang;
+#X obj 1483 612 + 0;
+#X obj 1467 584 * 0.1;
+#X obj 1504 584 * 0.15;
+#X obj 1575 608 + 0;
+#X obj 1555 581 * 0.1;
+#X obj 1596 580 * 0.15;
+#X obj 1662 609 + 0;
+#X obj 1755 610 + 0;
+#X text 1497 517 insert values at points here;
+#X obj 1646 581 * 30;
+#X obj 1683 581 * 60;
+#X obj 1736 581 * 60;
+#X obj 1776 582 * 90;
+#X obj 1774 549 float 0;
+#X obj 1492 551 float 1;
+#X obj 1633 551 float 0;
+#X obj 1706 549 float 0;
+#X text 1436 674 FM Amt;
+#X obj 1565 549 float 0.01;
+#X obj 1134 688 float 0.7;
+#X obj 1202 690 float 0.6;
+#X obj 1061 690 float 1;
+#X connect 0 0 130 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 4 0 21 0;
+#X connect 5 0 3 0;
+#X connect 6 0 15 0;
+#X connect 7 0 16 0;
+#X connect 8 0 17 0;
+#X connect 9 0 6 0;
+#X connect 10 0 6 1;
+#X connect 11 0 7 0;
+#X connect 12 0 7 1;
+#X connect 13 0 8 0;
+#X connect 14 0 8 1;
+#X connect 15 0 18 0;
+#X connect 16 0 19 0;
+#X connect 17 0 20 0;
+#X connect 18 0 21 1;
+#X connect 18 0 128 0;
+#X connect 19 0 22 0;
+#X connect 20 0 22 1;
+#X connect 20 0 126 0;
+#X connect 21 0 23 0;
+#X connect 22 0 23 1;
+#X connect 22 0 127 0;
+#X connect 23 0 148 0;
+#X connect 24 0 29 0;
+#X connect 25 0 33 0;
+#X connect 26 0 34 0;
+#X connect 27 0 35 0;
+#X connect 29 0 134 0;
+#X connect 30 0 133 0;
+#X connect 31 0 132 0;
+#X connect 32 0 131 0;
+#X connect 33 0 30 0;
+#X connect 34 0 31 0;
+#X connect 35 0 32 0;
+#X connect 37 0 42 0;
+#X connect 38 0 37 0;
+#X connect 39 0 90 0;
+#X connect 39 0 91 0;
+#X connect 39 0 92 0;
+#X connect 39 0 93 0;
+#X connect 39 0 94 0;
+#X connect 40 0 28 0;
+#X connect 41 0 44 0;
+#X connect 41 0 71 0;
+#X connect 41 0 99 0;
+#X connect 41 0 115 0;
+#X connect 41 0 154 0;
+#X connect 41 0 172 0;
+#X connect 42 0 43 0;
+#X connect 42 0 70 0;
+#X connect 42 0 98 0;
+#X connect 42 0 114 0;
+#X connect 42 0 153 0;
+#X connect 42 0 171 0;
+#X connect 43 0 40 0;
+#X connect 44 0 40 1;
+#X connect 45 0 28 0;
+#X connect 46 0 45 0;
+#X connect 47 0 45 1;
+#X connect 48 0 28 0;
+#X connect 49 0 28 0;
+#X connect 50 0 53 0;
+#X connect 51 0 50 0;
+#X connect 52 0 47 0;
+#X connect 52 0 74 0;
+#X connect 52 0 102 0;
+#X connect 52 0 118 0;
+#X connect 52 0 157 0;
+#X connect 52 0 175 0;
+#X connect 53 0 46 0;
+#X connect 53 0 73 0;
+#X connect 53 0 101 0;
+#X connect 53 0 117 0;
+#X connect 53 0 156 0;
+#X connect 53 0 174 0;
+#X connect 54 0 57 0;
+#X connect 55 0 54 0;
+#X connect 56 0 64 0;
+#X connect 56 0 79 0;
+#X connect 56 0 107 0;
+#X connect 56 0 123 0;
+#X connect 56 0 162 0;
+#X connect 56 0 180 0;
+#X connect 57 0 63 0;
+#X connect 57 0 78 0;
+#X connect 57 0 106 0;
+#X connect 57 0 122 0;
+#X connect 57 0 161 0;
+#X connect 57 0 179 0;
+#X connect 59 0 62 0;
+#X connect 60 0 59 0;
+#X connect 61 0 66 0;
+#X connect 61 0 81 0;
+#X connect 61 0 109 0;
+#X connect 61 0 125 0;
+#X connect 61 0 164 0;
+#X connect 61 0 182 0;
+#X connect 62 0 65 0;
+#X connect 62 0 80 0;
+#X connect 62 0 108 0;
+#X connect 62 0 124 0;
+#X connect 62 0 163 0;
+#X connect 62 0 181 0;
+#X connect 63 0 48 0;
+#X connect 64 0 48 1;
+#X connect 65 0 49 0;
+#X connect 66 0 49 1;
+#X connect 68 0 83 0;
+#X connect 68 0 84 0;
+#X connect 68 0 87 0;
+#X connect 68 0 88 0;
+#X connect 68 0 89 0;
+#X connect 69 0 67 0;
+#X connect 70 0 69 0;
+#X connect 71 0 69 1;
+#X connect 72 0 67 0;
+#X connect 73 0 72 0;
+#X connect 74 0 72 1;
+#X connect 75 0 67 0;
+#X connect 76 0 67 0;
+#X connect 78 0 75 0;
+#X connect 79 0 75 1;
+#X connect 80 0 76 0;
+#X connect 81 0 76 1;
+#X connect 83 0 70 1;
+#X connect 84 0 81 1;
+#X connect 87 0 71 1;
+#X connect 87 0 73 1;
+#X connect 88 0 74 1;
+#X connect 88 0 78 1;
+#X connect 89 0 79 1;
+#X connect 89 0 80 1;
+#X connect 90 0 43 1;
+#X connect 91 0 44 1;
+#X connect 91 0 46 1;
+#X connect 92 0 47 1;
+#X connect 92 0 63 1;
+#X connect 93 0 64 1;
+#X connect 93 0 65 1;
+#X connect 94 0 66 1;
+#X connect 96 0 143 0;
+#X connect 96 0 144 0;
+#X connect 96 0 145 0;
+#X connect 96 0 146 0;
+#X connect 96 0 149 0;
+#X connect 97 0 95 0;
+#X connect 98 0 97 0;
+#X connect 99 0 97 1;
+#X connect 100 0 95 0;
+#X connect 101 0 100 0;
+#X connect 102 0 100 1;
+#X connect 103 0 95 0;
+#X connect 104 0 95 0;
+#X connect 106 0 103 0;
+#X connect 107 0 103 1;
+#X connect 108 0 104 0;
+#X connect 109 0 104 1;
+#X connect 112 0 137 0;
+#X connect 112 0 139 0;
+#X connect 112 0 140 0;
+#X connect 112 0 141 0;
+#X connect 112 0 142 0;
+#X connect 113 0 111 0;
+#X connect 114 0 113 0;
+#X connect 115 0 113 1;
+#X connect 116 0 111 0;
+#X connect 117 0 116 0;
+#X connect 118 0 116 1;
+#X connect 119 0 111 0;
+#X connect 120 0 111 0;
+#X connect 122 0 119 0;
+#X connect 123 0 119 1;
+#X connect 124 0 120 0;
+#X connect 125 0 120 1;
+#X connect 126 0 22 0;
+#X connect 127 0 23 0;
+#X connect 128 0 21 0;
+#X connect 129 0 5 0;
+#X connect 129 1 2 0;
+#X connect 129 2 9 0;
+#X connect 129 3 10 0;
+#X connect 129 4 11 0;
+#X connect 129 5 12 0;
+#X connect 129 6 13 0;
+#X connect 129 7 14 0;
+#X connect 130 0 129 0;
+#X connect 130 1 148 1;
+#X connect 131 0 60 0;
+#X connect 131 1 59 1;
+#X connect 131 2 61 0;
+#X connect 132 0 55 0;
+#X connect 132 1 54 1;
+#X connect 132 2 56 0;
+#X connect 133 0 51 0;
+#X connect 133 1 50 1;
+#X connect 133 2 52 0;
+#X connect 134 0 38 0;
+#X connect 134 1 37 1;
+#X connect 134 2 41 0;
+#X connect 137 0 125 1;
+#X connect 139 0 114 1;
+#X connect 140 0 115 1;
+#X connect 140 0 117 1;
+#X connect 141 0 118 1;
+#X connect 141 0 122 1;
+#X connect 142 0 123 1;
+#X connect 142 0 124 1;
+#X connect 143 0 107 1;
+#X connect 143 0 108 1;
+#X connect 144 0 102 1;
+#X connect 144 0 106 1;
+#X connect 145 0 99 1;
+#X connect 145 0 101 1;
+#X connect 146 0 98 1;
+#X connect 147 0 24 0;
+#X connect 147 1 25 0;
+#X connect 147 2 26 0;
+#X connect 147 3 27 0;
+#X connect 148 0 147 0;
+#X connect 149 0 109 1;
+#X connect 151 0 165 0;
+#X connect 151 0 166 0;
+#X connect 151 0 189 0;
+#X connect 151 0 190 0;
+#X connect 151 0 191 0;
+#X connect 152 0 150 0;
+#X connect 153 0 152 0;
+#X connect 154 0 152 1;
+#X connect 155 0 150 0;
+#X connect 156 0 155 0;
+#X connect 157 0 155 1;
+#X connect 158 0 150 0;
+#X connect 159 0 150 0;
+#X connect 161 0 158 0;
+#X connect 162 0 158 1;
+#X connect 163 0 159 0;
+#X connect 164 0 159 1;
+#X connect 165 0 164 1;
+#X connect 166 0 162 1;
+#X connect 166 0 163 1;
+#X connect 169 0 183 0;
+#X connect 169 0 184 0;
+#X connect 169 0 185 0;
+#X connect 169 0 186 0;
+#X connect 169 0 188 0;
+#X connect 170 0 168 0;
+#X connect 171 0 170 0;
+#X connect 172 0 170 1;
+#X connect 173 0 168 0;
+#X connect 174 0 173 0;
+#X connect 175 0 173 1;
+#X connect 176 0 168 0;
+#X connect 177 0 168 0;
+#X connect 179 0 176 0;
+#X connect 180 0 176 1;
+#X connect 181 0 177 0;
+#X connect 182 0 177 1;
+#X connect 183 0 182 1;
+#X connect 184 0 171 1;
+#X connect 185 0 175 1;
+#X connect 185 0 179 1;
+#X connect 186 0 180 1;
+#X connect 186 0 181 1;
+#X connect 188 0 172 1;
+#X connect 188 0 174 1;
+#X connect 189 0 154 1;
+#X connect 189 0 156 1;
+#X connect 190 0 157 1;
+#X connect 190 0 161 1;
+#X connect 191 0 153 1;
+#X restore 44 163 pd interpolatorWave;
+#X floatatom 246 201 5 0 0 0 - - -;
+#X text 248 217 FMFreq;
+#X floatatom 289 199 5 0 0 0 - - -;
+#X text 291 215 FMAmt;
+#X obj 354 136 int 40;
+#X connect 0 0 15 0;
+#X connect 0 0 36 0;
+#X connect 1 0 4 0;
+#X connect 1 0 28 1;
+#X connect 4 0 7 0;
+#X connect 6 0 11 0;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 8 0 18 0;
+#X connect 10 0 58 0;
+#X connect 11 0 26 0;
+#X connect 13 0 16 0;
+#X connect 14 0 25 0;
+#X connect 15 0 14 0;
+#X connect 16 0 3 0;
+#X connect 17 0 32 0;
+#X connect 18 0 17 0;
+#X connect 19 0 8 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 29 0;
+#X connect 23 0 24 0;
+#X connect 24 0 27 0;
+#X connect 25 0 13 1;
+#X connect 26 0 3 0;
+#X connect 27 0 17 1;
+#X connect 28 0 19 0;
+#X connect 29 0 28 0;
+#X connect 31 0 22 0;
+#X connect 31 1 27 0;
+#X connect 32 0 6 1;
+#X connect 33 0 34 0;
+#X connect 34 0 35 0;
+#X connect 35 0 32 1;
+#X connect 36 0 13 0;
+#X connect 37 0 53 0;
+#X connect 38 0 53 0;
+#X connect 40 0 36 1;
+#X connect 41 0 25 1;
+#X connect 42 0 15 1;
+#X connect 43 0 26 1;
+#X connect 44 0 47 0;
+#X connect 45 0 48 0;
+#X connect 46 0 49 0;
+#X connect 47 0 37 0;
+#X connect 48 0 37 0;
+#X connect 49 0 37 0;
+#X connect 53 0 40 0;
+#X connect 53 1 41 0;
+#X connect 53 2 42 0;
+#X connect 53 3 43 0;
+#X connect 53 4 54 0;
+#X connect 53 5 56 0;
+#X connect 54 0 22 0;
+#X connect 56 0 27 0;
+#X connect 58 0 4 0;
+#X restore 76 221 pd oscillatorC;
+#N canvas 525 162 1052 736 fenvelopeC 0;
+#X obj 113 33 inlet;
+#X text 162 27 tribber;
+#X obj 347 0 inlet;
+#X obj 216 137 * 123;
+#X obj 306 163 * 123;
+#X text 474 63 proportion of level that is allways on;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 308 134 * 6;
+#X obj 123 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 262 301 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 260 395 pack 0 1;
+#X obj 469 289 f 1;
+#X obj 239 225 + 1;
+#X obj 142 341 f 1;
+#X obj 253 368 f 0;
+#X obj 309 271 + 3;
+#X obj 134 680 outlet~;
+#X text 82 678 filter;
+#X obj 316 461 *~ 1;
+#X obj 303 368 f 125;
+#X obj 182 339 f 1;
+#X obj 330 559 *~ 1;
+#X obj 306 191 + 10;
+#X obj 404 0 inlet;
+#X text 345 -20 attack;
+#X text 406 -23 decay;
+#X obj 494 5 inlet;
+#X text 488 -16 duration;
+#X obj 262 330 t b b;
+#X obj 121 203 t b b b;
+#X connect 0 0 10 0;
+#X connect 2 0 3 0;
+#X connect 3 0 16 0;
+#X connect 4 0 26 0;
+#X connect 6 0 22 1;
+#X connect 7 0 15 0;
+#X connect 7 1 6 1;
+#X connect 8 0 7 0;
+#X connect 9 0 4 0;
+#X connect 10 0 33 0;
+#X connect 11 0 32 0;
+#X connect 12 0 22 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 6 0;
+#X connect 16 0 19 0;
+#X connect 16 0 24 1;
+#X connect 17 0 13 0;
+#X connect 18 0 14 0;
+#X connect 19 0 11 1;
+#X connect 22 0 25 0;
+#X connect 23 0 14 1;
+#X connect 24 0 13 1;
+#X connect 25 0 20 0;
+#X connect 26 0 23 1;
+#X connect 27 0 9 0;
+#X connect 30 0 3 1;
+#X connect 30 0 4 1;
+#X connect 32 0 18 0;
+#X connect 32 1 23 0;
+#X connect 33 0 17 0;
+#X connect 33 1 24 0;
+#X connect 33 2 11 0;
+#X restore 167 221 pd fenvelopeC;
+#N canvas 867 125 1052 736 aenvelope 0;
+#X obj 113 33 inlet;
+#X obj 539 46 inlet;
+#X obj 216 137 * 123;
+#X obj 341 162 * 123;
+#X obj 468 202 route sustain;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 343 133 * 6;
+#X obj 341 190 + 50;
+#X obj 113 186 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 270 303 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 271 381 pack 0 1;
+#X obj 257 645 clip~ -1 1;
+#X obj 312 580 dbtorms~;
+#X obj 254 682 outlet~;
+#X obj 469 289 f 1;
+#X obj 316 520 *~ 60;
+#X obj 316 547 +~ 40;
+#X obj 218 161 + 1;
+#X obj 142 341 f 1;
+#X obj 269 349 f 0;
+#X obj 309 271 + 3;
+#X text 318 681 amplitude;
+#X obj 316 461 *~ 1;
+#X obj 318 490 +~ 0;
+#X obj 319 348 f 125;
+#X obj 182 339 f 1;
+#X obj 296 608 lop~ 50;
+#X obj 484 511 r fromOF;
+#X obj 481 565 route smoothing;
+#X obj 483 538 route list;
+#X obj 224 49 inlet;
+#X obj 322 49 inlet;
+#X text 232 28 attack;
+#X text 330 28 decay;
+#X text 162 28 trigger;
+#X text 532 18 total time;
+#X obj 237 225 t f f;
+#X obj 102 243 t b b b;
+#X obj 280 325 t b b;
+#X connect 0 0 10 0;
+#X connect 1 0 2 1;
+#X connect 1 0 3 1;
+#X connect 2 0 21 0;
+#X connect 3 0 9 0;
+#X connect 4 0 7 0;
+#X connect 5 0 26 1;
+#X connect 6 0 18 0;
+#X connect 6 1 5 1;
+#X connect 7 0 6 0;
+#X connect 7 0 27 1;
+#X connect 8 0 3 0;
+#X connect 9 0 28 1;
+#X connect 10 0 41 0;
+#X connect 11 0 23 0;
+#X connect 11 0 42 0;
+#X connect 12 0 26 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 17 0;
+#X connect 16 0 30 0;
+#X connect 18 0 5 0;
+#X connect 19 0 20 0;
+#X connect 20 0 16 0;
+#X connect 21 0 40 0;
+#X connect 22 0 13 0;
+#X connect 23 0 14 0;
+#X connect 24 0 11 1;
+#X connect 26 0 27 0;
+#X connect 27 0 19 0;
+#X connect 28 0 14 1;
+#X connect 29 0 13 1;
+#X connect 30 0 15 0;
+#X connect 31 0 33 0;
+#X connect 32 0 30 1;
+#X connect 33 0 32 0;
+#X connect 34 0 2 0;
+#X connect 35 0 8 0;
+#X connect 40 0 29 1;
+#X connect 40 1 24 0;
+#X connect 41 0 22 0;
+#X connect 41 1 29 0;
+#X connect 41 2 11 0;
+#X connect 42 0 23 0;
+#X connect 42 1 28 0;
+#X restore 259 222 pd aenvelope;
+#X text 182 -40 CANDIDATE;
+#X obj -40 33 / 127;
+#X obj -38 63 * 12;
+#X obj -42 102 + 40;
+#N canvas 0 22 450 300 ftypeResInterp 0;
+#X obj 140 50 inlet;
+#X obj 141 223 outlet;
+#X text 70 13 resonance peaks in middle for band pass \, and goes down
+at ends for lp and hp;
+#X obj 254 107 > 0.5;
+#X obj 232 151 spigot;
+#X obj 53 136 spigot;
+#X obj 97 96 <= 0.5;
+#X obj 53 96 * 255;
+#X obj 192 86 * -255;
+#X obj 200 117 + 255;
+#X connect 0 0 3 0;
+#X connect 0 0 7 0;
+#X connect 0 0 6 0;
+#X connect 0 0 8 0;
+#X connect 3 0 4 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 0;
+#X connect 6 0 5 1;
+#X connect 7 0 5 0;
+#X connect 8 0 9 0;
+#X connect 9 0 4 0;
+#X restore 210 75 pd ftypeResInterp;
+#X obj 344 82 * 0.8;
+#X obj 331 105 - 150;
+#X connect 2 0 6 0;
+#X connect 3 0 21 0;
+#X connect 3 0 22 0;
+#X connect 3 0 23 0;
+#X connect 3 0 24 0;
+#X connect 3 0 25 0;
+#X connect 3 0 26 0;
+#X connect 3 0 27 0;
+#X connect 3 0 28 0;
+#X connect 4 0 18 0;
+#X connect 5 0 0 0;
+#X connect 5 0 1 0;
+#X connect 6 0 37 0;
+#X connect 6 0 38 0;
+#X connect 7 0 37 1;
+#X connect 7 0 38 1;
+#X connect 8 0 37 2;
+#X connect 8 0 38 2;
+#X connect 13 0 29 2;
+#X connect 13 0 43 0;
+#X connect 18 0 5 0;
+#X connect 21 0 40 0;
+#X connect 22 0 36 0;
+#X connect 23 0 30 0;
+#X connect 24 0 31 0;
+#X connect 25 0 32 0;
+#X connect 26 0 33 0;
+#X connect 27 0 34 0;
+#X connect 28 0 35 0;
+#X connect 29 0 4 0;
+#X connect 30 0 7 0;
+#X connect 31 0 8 0;
+#X connect 32 0 13 0;
+#X connect 33 0 44 0;
+#X connect 36 0 29 0;
+#X connect 37 0 29 1;
+#X connect 38 0 4 1;
+#X connect 40 0 41 0;
+#X connect 41 0 42 0;
+#X connect 42 0 36 1;
+#X connect 43 0 29 4;
+#X connect 44 0 45 0;
+#X connect 45 0 29 3;
+#X restore 47 -40 pd candidateSynth;
+#N canvas 830 119 910 816 targetSynth 0;
+#X obj 83 467 outlet~;
+#X obj 143 466 outlet~;
+#X obj 659 -257 inlet;
+#X obj 181 -294 inlet;
+#X obj 96 296 *~;
+#X obj 73 375 clip~ -1 1;
+#X obj 664 -65 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 80 56 / 127;
+#X obj 119 57 / 127;
+#X text 81 -112 attack;
+#X text 124 -112 decay;
+#X text -53 -112 pitch;
+#X text -7 -114 duration;
+#X obj 258 49 / 127;
+#X text 299 -115 ftype;
+#X text 342 -115 ffreq;
+#X text 464 -117 reson;
+#X text 562 -111 reverb;
+#X obj 92 335 *~ 0.1;
+#X text 35 -102 wavef;
+#X text 655 -95 trigger;
+#X obj -38 -168 route pitch;
+#X obj 44 -169 route waveform;
+#X obj 138 -169 route attack;
+#X obj 221 -171 route decay;
+#X obj 301 -170 route fType;
+#X obj 378 -167 route fFreq;
+#X obj 459 -169 route reson;
+#X obj 547 -172 route reverb;
+#N canvas 42 77 1074 773 filterT 0;
+#X obj 44 22 inlet~;
+#X obj 165 84 route filtFreq;
+#X obj 855 112 route reson;
+#X obj 99 639 outlet~;
+#X obj 169 306 mtof~;
+#X obj 167 43 route list;
+#X obj 165 11 r fromOF;
+#X obj 316 19 inlet~;
+#X text 362 19 envelope;
+#X obj 171 189 sig~;
+#X obj 174 250 +~;
+#X obj 662 265 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 565 230 filetr freq;
+#X text 645 226 resonance;
+#X floatatom 822 416 5 0 0 0 - - -;
+#X msg 363 391 \$1 100;
+#X obj 363 415 line~;
+#X obj 407 303 hsl 128 15 0 1 0 1 empty empty empty -2 -8 0 10 -262144
+-1 -1 5600 1;
+#X text 284 273 Mode: 0 = lowpass \, 0.5 = resonant bandpass \, 1 =
+highpass;
+#X floatatom 403 356 5 0 0 0 - - -;
+#X obj 820 472 + 100;
+#X obj 820 496 dbtorms;
+#X floatatom 820 525 5 0 0 0 - - -;
+#X obj 820 443 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262144 -1 -1 3 256;
+#X obj 364 149 route fType;
+#X obj 820 356 / 5;
+#X obj 98 558 multimode_libpd.mmb~;
+#X obj 99 598 biquad_libpd.mmb~;
+#X floatatom 659 420 5 0 0 0 - - -;
+#X obj 167 280 clip~ 20 128;
+#X obj 169 220 lop~ 50;
+#X obj 169 122 * 0.6;
+#X obj 172 158 + 30;
+#X obj 238 221 *~ 110;
+#X obj 882 28 r fromOF;
+#X obj 815 553 lop~ 50;
+#X obj 881 57 route list;
+#X obj 891 81 route smoothing;
+#X text 38 2 audio in;
+#X text 478 17 ftype;
+#X text 590 17 ffreq;
+#X obj 544 17 inlet;
+#X obj 432 17 inlet;
+#X obj 646 17 inlet;
+#X text 692 17 reson;
+#X floatatom 195 386 5 0 0 0 - - -;
+#X obj 820 389 + 3;
+#X connect 0 0 27 0;
+#X connect 1 0 31 0;
+#X connect 2 0 25 0;
+#X connect 4 0 26 0;
+#X connect 5 0 1 0;
+#X connect 5 0 2 0;
+#X connect 5 0 24 0;
+#X connect 6 0 5 0;
+#X connect 7 0 33 0;
+#X connect 9 0 30 0;
+#X connect 10 0 29 0;
+#X connect 11 0 25 0;
+#X connect 11 0 28 0;
+#X connect 14 0 23 0;
+#X connect 15 0 16 0;
+#X connect 16 0 26 2;
+#X connect 17 0 19 0;
+#X connect 17 0 15 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 35 0;
+#X connect 23 0 20 0;
+#X connect 24 0 15 0;
+#X connect 25 0 46 0;
+#X connect 26 0 27 1;
+#X connect 26 1 27 2;
+#X connect 26 2 27 3;
+#X connect 26 3 27 4;
+#X connect 26 4 27 5;
+#X connect 27 0 3 0;
+#X connect 29 0 4 0;
+#X connect 30 0 10 0;
+#X connect 31 0 32 0;
+#X connect 32 0 9 0;
+#X connect 33 0 10 1;
+#X connect 34 0 36 0;
+#X connect 35 0 26 1;
+#X connect 36 0 37 0;
+#X connect 37 0 35 1;
+#X connect 37 0 30 1;
+#X connect 41 0 31 0;
+#X connect 42 0 15 0;
+#X connect 43 0 25 0;
+#X connect 46 0 14 0;
+#X restore 77 250 pd filterT;
+#X obj 92 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 120 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 268 -93 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 346 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 457 -94 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 565 -75 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#N canvas 76 137 871 723 oscillatorC 0;
+#X obj 83 269 phasor~;
+#X obj 430 -51 inlet;
+#X text 73 522 audio out;
+#X obj 79 501 outlet~;
+#X obj 402 171 mtof;
+#X text 292 -112 "pWidth" \, "sqVol" \, "sawVol" \, "sineVol" \, "FMAmt"
+;
+#X obj 321 233 +~;
+#X obj 402 193 sig~;
+#X floatatom 564 131 5 0 0 0 - - -;
+#X text 627 93 fm rfeq;
+#X obj 353 113 loadbang;
+#X obj 262 398 osc~ 220;
+#X text 29 390 subtract out of phase one;
+#X obj 84 377 -~;
+#X obj 151 327 wrap~;
+#X obj 150 302 +~ 0.5;
+#X obj 83 437 -~ 0.5;
+#X obj 568 186 *~ 0;
+#X obj 562 156 osc~;
+#X obj 561 105 mtof;
+#X obj 731 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 723 64 / 127;
+#X obj 548 29 * 100;
+#X obj 765 -85 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 764 62 / 127;
+#X obj 152 354 *~ 0;
+#X obj 263 429 *~ 1;
+#X obj 616 129 * 3500;
+#X obj 559 81 +;
+#X obj 560 54 - 40;
+#X text 408 -73 pitch freq;
+#X obj 552 1 route FMFreq FMAmt;
+#X obj 564 218 lop~ 20;
+#X obj 680 172 r fromOF;
+#X obj 679 201 route list;
+#X obj 677 226 route smoothing;
+#X obj 84 346 *~ 1;
+#X obj 66 124 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 16 122 inlet;
+#X text 52 93 waveform;
+#X floatatom 42 198 5 0 0 0 - - -;
+#X floatatom 93 201 5 0 0 0 - - -;
+#X floatatom 141 205 5 0 0 0 - - -;
+#X floatatom 190 203 5 0 0 0 - - -;
+#X obj 29 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 101 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 170 -14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 31 19 float 10;
+#X obj 103 19 float 64;
+#X obj 173 21 float 120;
+#X text 192 219 sineVol;
+#X text 30 218 saw vol;
+#X text 92 221 sq vol;
+#N canvas 71 22 1849 1017 interpolatorWave 0;
+#X obj 80 -91 inlet;
+#X text 75 -113 slider control;
+#X obj 217 74 < 32;
+#X obj 202 100 &&;
+#X floatatom 211 122 5 0 0 0 - - -;
+#X obj 186 74 >= 0;
+#X obj 279 99 &&;
+#X obj 359 98 &&;
+#X obj 444 97 &&;
+#X obj 263 73 >= 32;
+#X obj 300 73 < 64;
+#X obj 339 73 >= 64;
+#X obj 380 72 < 96;
+#X obj 428 71 >= 96;
+#X obj 465 71 < 128;
+#X floatatom 273 121 5 0 0 0 - - -;
+#X floatatom 354 119 5 0 0 0 - - -;
+#X floatatom 438 118 5 0 0 0 - - -;
+#X obj 273 148 * 2;
+#X obj 355 147 * 3;
+#X obj 436 147 * 4;
+#X obj 246 205 +;
+#X obj 398 200 +;
+#X obj 315 246 +;
+#X floatatom 105 352 5 0 0 0 - - -;
+#X floatatom 181 356 5 0 0 0 - - -;
+#X floatatom 246 356 5 0 0 0 - - -;
+#X floatatom 316 352 5 0 0 0 - - -;
+#X obj -125 824 outlet;
+#X obj 116 408 / 32;
+#X obj 181 408 / 32;
+#X obj 243 410 / 32;
+#X obj 316 408 / 32;
+#X obj 177 381 - 32;
+#X obj 245 382 - 64;
+#X obj 317 378 - 96;
+#X text 544 477 calc frac;
+#X obj 35 498 -;
+#X obj 35 479 float 1;
+#X obj 159 626 loadbang;
+#X obj -134 764 + 0;
+#X floatatom 85 526 5 0 0 0 - - -;
+#X floatatom 36 527 5 0 0 0 - - -;
+#X obj -150 736 * 0.1;
+#X obj -113 736 * 0.15;
+#X obj -42 760 + 0;
+#X obj -58 732 * 0.1;
+#X obj -21 732 * 0.15;
+#X obj 45 761 + 0;
+#X obj 138 762 + 0;
+#X obj 153 506 -;
+#X obj 153 487 float 1;
+#X floatatom 200 526 5 0 0 0 - - -;
+#X floatatom 154 528 5 0 0 0 - - -;
+#X obj 286 502 -;
+#X obj 286 483 float 1;
+#X floatatom 335 526 5 0 0 0 - - -;
+#X floatatom 287 524 5 0 0 0 - - -;
+#X text 6 678 insert values at points here;
+#X obj 416 505 -;
+#X obj 416 486 float 1;
+#X floatatom 467 526 5 0 0 0 - - -;
+#X floatatom 417 527 5 0 0 0 - - -;
+#X obj 29 733 * 30;
+#X obj 66 733 * 60;
+#X obj 119 733 * 60;
+#X obj 159 734 * 90;
+#X obj -543 849 outlet;
+#X obj -557 676 loadbang;
+#X obj -552 789 + 0;
+#X obj -568 761 * 0.1;
+#X obj -531 761 * 0.15;
+#X obj -460 785 + 0;
+#X obj -476 757 * 0.1;
+#X obj -439 757 * 0.15;
+#X obj -373 786 + 0;
+#X obj -280 787 + 0;
+#X text -630 702 insert values at points here;
+#X obj -389 758 * 30;
+#X obj -352 758 * 60;
+#X obj -299 758 * 60;
+#X obj -259 759 * 90;
+#X text -541 827 comment;
+#X obj -543 728 float 0;
+#X obj -262 725 float 1;
+#X text -595 848 saw vol;
+#X text -207 825 pulse volume;
+#X obj -470 726 float 0;
+#X obj -402 728 float 1;
+#X obj -330 726 float 1;
+#X obj -125 703 float 0;
+#X obj -52 701 float 0;
+#X obj 16 703 float 0;
+#X obj 88 701 float 1;
+#X obj 157 701 float 1;
+#X obj 264 818 outlet;
+#X obj 548 620 loadbang;
+#X obj 255 758 + 0;
+#X obj 239 730 * 0.1;
+#X obj 276 730 * 0.15;
+#X obj 347 754 + 0;
+#X obj 331 726 * 0.1;
+#X obj 368 726 * 0.15;
+#X obj 434 755 + 0;
+#X obj 527 756 + 0;
+#X text 373 667 insert values at points here;
+#X obj 418 727 * 30;
+#X obj 455 727 * 60;
+#X obj 508 727 * 60;
+#X obj 548 728 * 90;
+#X text 182 819 pulse width;
+#X obj 677 819 outlet;
+#X obj 961 621 loadbang;
+#X obj 668 759 + 0;
+#X obj 652 731 * 0.1;
+#X obj 689 731 * 0.15;
+#X obj 760 755 + 0;
+#X obj 744 727 * 0.1;
+#X obj 781 727 * 0.15;
+#X obj 847 756 + 0;
+#X obj 940 757 + 0;
+#X text 682 664 insert values at points here;
+#X obj 831 728 * 30;
+#X obj 868 728 * 60;
+#X obj 921 728 * 60;
+#X obj 961 729 * 90;
+#X obj 397 174 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 315 224 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 246 175 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 255 28 t f f f f f f f f;
+#X obj 117 -57 t f f;
+#X obj 415 462 t b f f;
+#X obj 283 458 t b f f;
+#X obj 155 463 t b f f;
+#X obj 36 452 t b f f;
+#X text 266 796 comment;
+#X text -124 801 comment;
+#X obj 959 696 float 0;
+#X text 595 820 sine volume;
+#X obj 677 698 float 1;
+#X obj 750 696 float 1;
+#X obj 818 698 float 0;
+#X obj 891 696 float 0;
+#X obj 477 695 float 0.5;
+#X obj 405 697 float 0.5;
+#X obj 337 695 float 0.5;
+#X obj 264 697 float 0.5;
+#X obj 166 308 route 1 2 3 4;
+#X obj 164 281 pack;
+#X obj 546 695 float 0.01;
+#X obj 1061 811 outlet;
+#X obj 1345 613 loadbang;
+#X obj 1052 751 + 0;
+#X obj 1036 723 * 0.1;
+#X obj 1073 723 * 0.15;
+#X obj 1144 747 + 0;
+#X obj 1124 720 * 0.1;
+#X obj 1165 719 * 0.15;
+#X obj 1231 748 + 0;
+#X obj 1324 749 + 0;
+#X text 1066 656 insert values at points here;
+#X obj 1215 720 * 30;
+#X obj 1252 720 * 60;
+#X obj 1305 720 * 60;
+#X obj 1345 721 * 90;
+#X obj 1343 688 float 0;
+#X obj 1275 688 float 0;
+#X text 979 812 FM Freq;
+#X obj 1492 672 outlet;
+#X obj 1776 474 loadbang;
+#X obj 1483 612 + 0;
+#X obj 1467 584 * 0.1;
+#X obj 1504 584 * 0.15;
+#X obj 1575 608 + 0;
+#X obj 1555 581 * 0.1;
+#X obj 1596 580 * 0.15;
+#X obj 1662 609 + 0;
+#X obj 1755 610 + 0;
+#X text 1497 517 insert values at points here;
+#X obj 1646 581 * 30;
+#X obj 1683 581 * 60;
+#X obj 1736 581 * 60;
+#X obj 1776 582 * 90;
+#X obj 1774 549 float 0;
+#X obj 1492 551 float 1;
+#X obj 1633 551 float 0;
+#X obj 1706 549 float 0;
+#X text 1436 674 FM Amt;
+#X obj 1565 549 float 0.01;
+#X obj 1134 688 float 0.7;
+#X obj 1202 690 float 0.6;
+#X obj 1061 690 float 1;
+#X connect 0 0 130 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 4 0 21 0;
+#X connect 5 0 3 0;
+#X connect 6 0 15 0;
+#X connect 7 0 16 0;
+#X connect 8 0 17 0;
+#X connect 9 0 6 0;
+#X connect 10 0 6 1;
+#X connect 11 0 7 0;
+#X connect 12 0 7 1;
+#X connect 13 0 8 0;
+#X connect 14 0 8 1;
+#X connect 15 0 18 0;
+#X connect 16 0 19 0;
+#X connect 17 0 20 0;
+#X connect 18 0 21 1;
+#X connect 18 0 128 0;
+#X connect 19 0 22 0;
+#X connect 20 0 22 1;
+#X connect 20 0 126 0;
+#X connect 21 0 23 0;
+#X connect 22 0 23 1;
+#X connect 22 0 127 0;
+#X connect 23 0 148 0;
+#X connect 24 0 29 0;
+#X connect 25 0 33 0;
+#X connect 26 0 34 0;
+#X connect 27 0 35 0;
+#X connect 29 0 134 0;
+#X connect 30 0 133 0;
+#X connect 31 0 132 0;
+#X connect 32 0 131 0;
+#X connect 33 0 30 0;
+#X connect 34 0 31 0;
+#X connect 35 0 32 0;
+#X connect 37 0 42 0;
+#X connect 38 0 37 0;
+#X connect 39 0 90 0;
+#X connect 39 0 91 0;
+#X connect 39 0 92 0;
+#X connect 39 0 93 0;
+#X connect 39 0 94 0;
+#X connect 40 0 28 0;
+#X connect 41 0 44 0;
+#X connect 41 0 71 0;
+#X connect 41 0 99 0;
+#X connect 41 0 115 0;
+#X connect 41 0 154 0;
+#X connect 41 0 172 0;
+#X connect 42 0 43 0;
+#X connect 42 0 70 0;
+#X connect 42 0 98 0;
+#X connect 42 0 114 0;
+#X connect 42 0 153 0;
+#X connect 42 0 171 0;
+#X connect 43 0 40 0;
+#X connect 44 0 40 1;
+#X connect 45 0 28 0;
+#X connect 46 0 45 0;
+#X connect 47 0 45 1;
+#X connect 48 0 28 0;
+#X connect 49 0 28 0;
+#X connect 50 0 53 0;
+#X connect 51 0 50 0;
+#X connect 52 0 47 0;
+#X connect 52 0 74 0;
+#X connect 52 0 102 0;
+#X connect 52 0 118 0;
+#X connect 52 0 157 0;
+#X connect 52 0 175 0;
+#X connect 53 0 46 0;
+#X connect 53 0 73 0;
+#X connect 53 0 101 0;
+#X connect 53 0 117 0;
+#X connect 53 0 156 0;
+#X connect 53 0 174 0;
+#X connect 54 0 57 0;
+#X connect 55 0 54 0;
+#X connect 56 0 64 0;
+#X connect 56 0 79 0;
+#X connect 56 0 107 0;
+#X connect 56 0 123 0;
+#X connect 56 0 162 0;
+#X connect 56 0 180 0;
+#X connect 57 0 63 0;
+#X connect 57 0 78 0;
+#X connect 57 0 106 0;
+#X connect 57 0 122 0;
+#X connect 57 0 161 0;
+#X connect 57 0 179 0;
+#X connect 59 0 62 0;
+#X connect 60 0 59 0;
+#X connect 61 0 66 0;
+#X connect 61 0 81 0;
+#X connect 61 0 109 0;
+#X connect 61 0 125 0;
+#X connect 61 0 164 0;
+#X connect 61 0 182 0;
+#X connect 62 0 65 0;
+#X connect 62 0 80 0;
+#X connect 62 0 108 0;
+#X connect 62 0 124 0;
+#X connect 62 0 163 0;
+#X connect 62 0 181 0;
+#X connect 63 0 48 0;
+#X connect 64 0 48 1;
+#X connect 65 0 49 0;
+#X connect 66 0 49 1;
+#X connect 68 0 83 0;
+#X connect 68 0 84 0;
+#X connect 68 0 87 0;
+#X connect 68 0 88 0;
+#X connect 68 0 89 0;
+#X connect 69 0 67 0;
+#X connect 70 0 69 0;
+#X connect 71 0 69 1;
+#X connect 72 0 67 0;
+#X connect 73 0 72 0;
+#X connect 74 0 72 1;
+#X connect 75 0 67 0;
+#X connect 76 0 67 0;
+#X connect 78 0 75 0;
+#X connect 79 0 75 1;
+#X connect 80 0 76 0;
+#X connect 81 0 76 1;
+#X connect 83 0 70 1;
+#X connect 84 0 81 1;
+#X connect 87 0 71 1;
+#X connect 87 0 73 1;
+#X connect 88 0 74 1;
+#X connect 88 0 78 1;
+#X connect 89 0 79 1;
+#X connect 89 0 80 1;
+#X connect 90 0 43 1;
+#X connect 91 0 44 1;
+#X connect 91 0 46 1;
+#X connect 92 0 47 1;
+#X connect 92 0 63 1;
+#X connect 93 0 64 1;
+#X connect 93 0 65 1;
+#X connect 94 0 66 1;
+#X connect 96 0 143 0;
+#X connect 96 0 144 0;
+#X connect 96 0 145 0;
+#X connect 96 0 146 0;
+#X connect 96 0 149 0;
+#X connect 97 0 95 0;
+#X connect 98 0 97 0;
+#X connect 99 0 97 1;
+#X connect 100 0 95 0;
+#X connect 101 0 100 0;
+#X connect 102 0 100 1;
+#X connect 103 0 95 0;
+#X connect 104 0 95 0;
+#X connect 106 0 103 0;
+#X connect 107 0 103 1;
+#X connect 108 0 104 0;
+#X connect 109 0 104 1;
+#X connect 112 0 137 0;
+#X connect 112 0 139 0;
+#X connect 112 0 140 0;
+#X connect 112 0 141 0;
+#X connect 112 0 142 0;
+#X connect 113 0 111 0;
+#X connect 114 0 113 0;
+#X connect 115 0 113 1;
+#X connect 116 0 111 0;
+#X connect 117 0 116 0;
+#X connect 118 0 116 1;
+#X connect 119 0 111 0;
+#X connect 120 0 111 0;
+#X connect 122 0 119 0;
+#X connect 123 0 119 1;
+#X connect 124 0 120 0;
+#X connect 125 0 120 1;
+#X connect 126 0 22 0;
+#X connect 127 0 23 0;
+#X connect 128 0 21 0;
+#X connect 129 0 5 0;
+#X connect 129 1 2 0;
+#X connect 129 2 9 0;
+#X connect 129 3 10 0;
+#X connect 129 4 11 0;
+#X connect 129 5 12 0;
+#X connect 129 6 13 0;
+#X connect 129 7 14 0;
+#X connect 130 0 129 0;
+#X connect 130 1 148 1;
+#X connect 131 0 60 0;
+#X connect 131 1 59 1;
+#X connect 131 2 61 0;
+#X connect 132 0 55 0;
+#X connect 132 1 54 1;
+#X connect 132 2 56 0;
+#X connect 133 0 51 0;
+#X connect 133 1 50 1;
+#X connect 133 2 52 0;
+#X connect 134 0 38 0;
+#X connect 134 1 37 1;
+#X connect 134 2 41 0;
+#X connect 137 0 125 1;
+#X connect 139 0 114 1;
+#X connect 140 0 115 1;
+#X connect 140 0 117 1;
+#X connect 141 0 118 1;
+#X connect 141 0 122 1;
+#X connect 142 0 123 1;
+#X connect 142 0 124 1;
+#X connect 143 0 107 1;
+#X connect 143 0 108 1;
+#X connect 144 0 102 1;
+#X connect 144 0 106 1;
+#X connect 145 0 99 1;
+#X connect 145 0 101 1;
+#X connect 146 0 98 1;
+#X connect 147 0 24 0;
+#X connect 147 1 25 0;
+#X connect 147 2 26 0;
+#X connect 147 3 27 0;
+#X connect 148 0 147 0;
+#X connect 149 0 109 1;
+#X connect 151 0 165 0;
+#X connect 151 0 166 0;
+#X connect 151 0 189 0;
+#X connect 151 0 190 0;
+#X connect 151 0 191 0;
+#X connect 152 0 150 0;
+#X connect 153 0 152 0;
+#X connect 154 0 152 1;
+#X connect 155 0 150 0;
+#X connect 156 0 155 0;
+#X connect 157 0 155 1;
+#X connect 158 0 150 0;
+#X connect 159 0 150 0;
+#X connect 161 0 158 0;
+#X connect 162 0 158 1;
+#X connect 163 0 159 0;
+#X connect 164 0 159 1;
+#X connect 165 0 164 1;
+#X connect 166 0 162 1;
+#X connect 166 0 163 1;
+#X connect 169 0 183 0;
+#X connect 169 0 184 0;
+#X connect 169 0 185 0;
+#X connect 169 0 186 0;
+#X connect 169 0 188 0;
+#X connect 170 0 168 0;
+#X connect 171 0 170 0;
+#X connect 172 0 170 1;
+#X connect 173 0 168 0;
+#X connect 174 0 173 0;
+#X connect 175 0 173 1;
+#X connect 176 0 168 0;
+#X connect 177 0 168 0;
+#X connect 179 0 176 0;
+#X connect 180 0 176 1;
+#X connect 181 0 177 0;
+#X connect 182 0 177 1;
+#X connect 183 0 182 1;
+#X connect 184 0 171 1;
+#X connect 185 0 175 1;
+#X connect 185 0 179 1;
+#X connect 186 0 180 1;
+#X connect 186 0 181 1;
+#X connect 188 0 172 1;
+#X connect 188 0 174 1;
+#X connect 189 0 154 1;
+#X connect 189 0 156 1;
+#X connect 190 0 157 1;
+#X connect 190 0 161 1;
+#X connect 191 0 153 1;
+#X restore 44 163 pd interpolatorWave;
+#X floatatom 246 201 5 0 0 0 - - -;
+#X text 248 217 FMFreq;
+#X floatatom 289 199 5 0 0 0 - - -;
+#X text 291 215 FMAmt;
+#X obj 354 136 int 40;
+#X connect 0 0 15 0;
+#X connect 0 0 36 0;
+#X connect 1 0 4 0;
+#X connect 1 0 28 1;
+#X connect 4 0 7 0;
+#X connect 6 0 11 0;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 8 0 18 0;
+#X connect 10 0 58 0;
+#X connect 11 0 26 0;
+#X connect 13 0 16 0;
+#X connect 14 0 25 0;
+#X connect 15 0 14 0;
+#X connect 16 0 3 0;
+#X connect 17 0 32 0;
+#X connect 18 0 17 0;
+#X connect 19 0 8 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 29 0;
+#X connect 23 0 24 0;
+#X connect 24 0 27 0;
+#X connect 25 0 13 1;
+#X connect 26 0 3 0;
+#X connect 27 0 17 1;
+#X connect 28 0 19 0;
+#X connect 29 0 28 0;
+#X connect 31 0 22 0;
+#X connect 31 1 27 0;
+#X connect 32 0 6 1;
+#X connect 33 0 34 0;
+#X connect 34 0 35 0;
+#X connect 35 0 32 1;
+#X connect 36 0 13 0;
+#X connect 37 0 53 0;
+#X connect 38 0 53 0;
+#X connect 40 0 36 1;
+#X connect 41 0 25 1;
+#X connect 42 0 15 1;
+#X connect 43 0 26 1;
+#X connect 44 0 47 0;
+#X connect 45 0 48 0;
+#X connect 46 0 49 0;
+#X connect 47 0 37 0;
+#X connect 48 0 37 0;
+#X connect 49 0 37 0;
+#X connect 53 0 40 0;
+#X connect 53 1 41 0;
+#X connect 53 2 42 0;
+#X connect 53 3 43 0;
+#X connect 53 4 54 0;
+#X connect 53 5 56 0;
+#X connect 54 0 22 0;
+#X connect 56 0 27 0;
+#X connect 58 0 4 0;
+#X restore 76 221 pd oscillatorC;
+#N canvas 525 162 1052 736 fenvelopeC 0;
+#X obj 113 33 inlet;
+#X text 162 27 tribber;
+#X obj 347 0 inlet;
+#X obj 216 137 * 123;
+#X obj 306 163 * 123;
+#X text 474 63 proportion of level that is allways on;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 308 134 * 6;
+#X obj 123 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 262 301 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 260 395 pack 0 1;
+#X obj 469 289 f 1;
+#X obj 239 225 + 1;
+#X obj 142 341 f 1;
+#X obj 253 368 f 0;
+#X obj 309 271 + 3;
+#X obj 134 680 outlet~;
+#X text 82 678 filter;
+#X obj 316 461 *~ 1;
+#X obj 303 368 f 125;
+#X obj 182 339 f 1;
+#X obj 330 559 *~ 1;
+#X obj 306 191 + 10;
+#X obj 404 0 inlet;
+#X text 345 -20 attack;
+#X text 406 -23 decay;
+#X obj 494 5 inlet;
+#X text 488 -16 duration;
+#X obj 262 330 t b b;
+#X obj 121 203 t b b b;
+#X connect 0 0 10 0;
+#X connect 2 0 3 0;
+#X connect 3 0 16 0;
+#X connect 4 0 26 0;
+#X connect 6 0 22 1;
+#X connect 7 0 15 0;
+#X connect 7 1 6 1;
+#X connect 8 0 7 0;
+#X connect 9 0 4 0;
+#X connect 10 0 33 0;
+#X connect 11 0 32 0;
+#X connect 12 0 22 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 6 0;
+#X connect 16 0 19 0;
+#X connect 16 0 24 1;
+#X connect 17 0 13 0;
+#X connect 18 0 14 0;
+#X connect 19 0 11 1;
+#X connect 22 0 25 0;
+#X connect 23 0 14 1;
+#X connect 24 0 13 1;
+#X connect 25 0 20 0;
+#X connect 26 0 23 1;
+#X connect 27 0 9 0;
+#X connect 30 0 3 1;
+#X connect 30 0 4 1;
+#X connect 32 0 18 0;
+#X connect 32 1 23 0;
+#X connect 33 0 17 0;
+#X connect 33 1 24 0;
+#X connect 33 2 11 0;
+#X restore 167 221 pd fenvelopeC;
+#N canvas 867 125 1052 736 aenvelope 0;
+#X obj 113 33 inlet;
+#X obj 539 46 inlet;
+#X obj 216 137 * 123;
+#X obj 341 162 * 123;
+#X obj 468 202 route sustain;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 343 133 * 6;
+#X obj 341 190 + 50;
+#X obj 113 186 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 270 303 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 271 381 pack 0 1;
+#X obj 257 645 clip~ -1 1;
+#X obj 312 580 dbtorms~;
+#X obj 254 682 outlet~;
+#X obj 469 289 f 1;
+#X obj 316 520 *~ 60;
+#X obj 316 547 +~ 40;
+#X obj 218 161 + 1;
+#X obj 142 341 f 1;
+#X obj 269 349 f 0;
+#X obj 309 271 + 3;
+#X text 318 681 amplitude;
+#X obj 316 461 *~ 1;
+#X obj 318 490 +~ 0;
+#X obj 319 348 f 125;
+#X obj 182 339 f 1;
+#X obj 296 608 lop~ 50;
+#X obj 484 511 r fromOF;
+#X obj 481 565 route smoothing;
+#X obj 483 538 route list;
+#X obj 224 49 inlet;
+#X obj 322 49 inlet;
+#X text 232 28 attack;
+#X text 330 28 decay;
+#X text 162 28 trigger;
+#X text 532 18 total time;
+#X obj 237 225 t f f;
+#X obj 102 243 t b b b;
+#X obj 280 325 t b b;
+#X connect 0 0 10 0;
+#X connect 1 0 2 1;
+#X connect 1 0 3 1;
+#X connect 2 0 21 0;
+#X connect 3 0 9 0;
+#X connect 4 0 7 0;
+#X connect 5 0 26 1;
+#X connect 6 0 18 0;
+#X connect 6 1 5 1;
+#X connect 7 0 6 0;
+#X connect 7 0 27 1;
+#X connect 8 0 3 0;
+#X connect 9 0 28 1;
+#X connect 10 0 41 0;
+#X connect 11 0 23 0;
+#X connect 11 0 42 0;
+#X connect 12 0 26 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 17 0;
+#X connect 16 0 30 0;
+#X connect 18 0 5 0;
+#X connect 19 0 20 0;
+#X connect 20 0 16 0;
+#X connect 21 0 40 0;
+#X connect 22 0 13 0;
+#X connect 23 0 14 0;
+#X connect 24 0 11 1;
+#X connect 26 0 27 0;
+#X connect 27 0 19 0;
+#X connect 28 0 14 1;
+#X connect 29 0 13 1;
+#X connect 30 0 15 0;
+#X connect 31 0 33 0;
+#X connect 32 0 30 1;
+#X connect 33 0 32 0;
+#X connect 34 0 2 0;
+#X connect 35 0 8 0;
+#X connect 40 0 29 1;
+#X connect 40 1 24 0;
+#X connect 41 0 22 0;
+#X connect 41 1 29 0;
+#X connect 41 2 11 0;
+#X connect 42 0 23 0;
+#X connect 42 1 28 0;
+#X restore 259 222 pd aenvelope;
+#X obj -40 33 / 127;
+#X obj -38 63 * 12;
+#X obj -42 102 + 40;
+#N canvas 0 22 450 300 ftypeResInterp 0;
+#X obj 140 50 inlet;
+#X obj 141 223 outlet;
+#X text 70 13 resonance peaks in middle for band pass \, and goes down
+at ends for lp and hp;
+#X obj 254 107 > 0.5;
+#X obj 232 151 spigot;
+#X obj 53 136 spigot;
+#X obj 97 96 <= 0.5;
+#X obj 53 96 * 255;
+#X obj 192 86 * -255;
+#X obj 200 117 + 255;
+#X connect 0 0 3 0;
+#X connect 0 0 7 0;
+#X connect 0 0 6 0;
+#X connect 0 0 8 0;
+#X connect 3 0 4 1;
+#X connect 4 0 1 0;
+#X connect 5 0 1 0;
+#X connect 6 0 5 1;
+#X connect 7 0 5 0;
+#X connect 8 0 9 0;
+#X connect 9 0 4 0;
+#X restore 210 75 pd ftypeResInterp;
+#X obj 344 82 * 0.8;
+#X obj 331 105 - 150;
+#X text 184 -41 TARGET;
+#X connect 2 0 6 0;
+#X connect 3 0 21 0;
+#X connect 3 0 22 0;
+#X connect 3 0 23 0;
+#X connect 3 0 24 0;
+#X connect 3 0 25 0;
+#X connect 3 0 26 0;
+#X connect 3 0 27 0;
+#X connect 3 0 28 0;
+#X connect 4 0 18 0;
+#X connect 5 0 0 0;
+#X connect 5 0 1 0;
+#X connect 6 0 37 0;
+#X connect 6 0 38 0;
+#X connect 7 0 37 1;
+#X connect 7 0 38 1;
+#X connect 8 0 37 2;
+#X connect 8 0 38 2;
+#X connect 13 0 29 2;
+#X connect 13 0 42 0;
+#X connect 18 0 5 0;
+#X connect 21 0 39 0;
+#X connect 22 0 36 0;
+#X connect 23 0 30 0;
+#X connect 24 0 31 0;
+#X connect 25 0 32 0;
+#X connect 26 0 33 0;
+#X connect 27 0 34 0;
+#X connect 28 0 35 0;
+#X connect 29 0 4 0;
+#X connect 30 0 7 0;
+#X connect 31 0 8 0;
+#X connect 32 0 13 0;
+#X connect 33 0 43 0;
+#X connect 36 0 29 0;
+#X connect 37 0 29 1;
+#X connect 38 0 4 1;
+#X connect 39 0 40 0;
+#X connect 40 0 41 0;
+#X connect 41 0 36 1;
+#X connect 42 0 29 4;
+#X connect 43 0 44 0;
+#X connect 44 0 29 3;
+#X restore 215 -31 pd targetSynth;
+#X connect 1 0 0 0;
+#X connect 2 0 0 1;
+#X connect 5 0 20 1;
+#X connect 6 0 21 1;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 8 0 10 0;
+#X connect 8 0 15 0;
+#X connect 9 0 18 0;
+#X connect 9 0 20 0;
+#X connect 10 0 17 0;
+#X connect 10 0 21 0;
+#X connect 11 0 5 0;
+#X connect 11 1 6 0;
+#X connect 12 0 11 0;
+#X connect 13 0 14 0;
+#X connect 14 0 11 1;
+#X connect 15 0 12 0;
+#X connect 16 0 19 0;
+#X connect 17 0 6 0;
+#X connect 18 0 5 0;
+#X connect 19 0 12 0;
+#X connect 20 0 1 0;
+#X connect 20 1 2 0;
+#X connect 21 0 1 1;
+#X connect 21 1 2 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targetSynth6.pd	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,2350 @@
+#N canvas 898 149 1013 774 10;
+#X obj 109 189 dac~;
+#X obj 70 -182 metro 500;
+#X obj 44 -258 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#N canvas 903 68 910 816 targetSynth 0;
+#N canvas 76 137 871 723 oscillator 0;
+#X obj 83 269 phasor~;
+#X obj 430 -51 inlet;
+#X text 73 522 audio out;
+#X obj 79 501 outlet~;
+#X obj 402 171 mtof;
+#X text 292 -112 "pWidth" \, "sqVol" \, "sawVol" \, "sineVol" \, "FMAmt"
+;
+#X obj 321 233 +~;
+#X obj 402 193 sig~;
+#X floatatom 564 131 5 0 0 0 - - -;
+#X text 627 93 fm rfeq;
+#X obj 354 136 int 64;
+#X obj 353 113 loadbang;
+#X obj 262 398 osc~ 220;
+#X text 29 390 subtract out of phase one;
+#X obj 84 377 -~;
+#X obj 151 327 wrap~;
+#X obj 150 302 +~ 0.5;
+#X obj 83 437 -~ 0.5;
+#X obj 568 186 *~ 0;
+#X obj 562 156 osc~;
+#X obj 561 105 mtof;
+#X obj 731 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 723 64 / 127;
+#X obj 548 29 * 100;
+#X obj 765 -85 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 764 62 / 127;
+#X obj 152 354 *~ 0;
+#X obj 263 429 *~ 1;
+#X obj 616 129 * 3500;
+#X obj 559 81 +;
+#X obj 560 54 - 40;
+#X text 408 -73 pitch freq;
+#X obj 552 1 route FMFreq FMAmt;
+#X obj 564 218 lop~ 20;
+#X obj 680 172 r fromOF;
+#X obj 679 201 route list;
+#X obj 677 226 route smoothing;
+#X obj 84 346 *~ 1;
+#X obj 62 124 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 12700 1;
+#X obj 16 122 inlet;
+#X text 52 93 waveform;
+#X floatatom 42 198 5 0 0 0 - - -;
+#X floatatom 93 201 5 0 0 0 - - -;
+#X floatatom 141 205 5 0 0 0 - - -;
+#X floatatom 190 203 5 0 0 0 - - -;
+#X obj 29 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 101 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 170 -14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 31 19 float 10;
+#X obj 103 19 float 64;
+#X obj 173 21 float 120;
+#X text 192 219 sineVol;
+#X text 30 218 saw vol;
+#X text 92 221 sq vol;
+#N canvas 584 22 1336 1017 interpolatorWave 0;
+#X obj 80 -91 inlet;
+#X text 75 -113 slider control;
+#X obj 217 74 < 32;
+#X obj 202 100 &&;
+#X floatatom 211 122 5 0 0 0 - - -;
+#X obj 186 74 >= 0;
+#X obj 279 99 &&;
+#X obj 359 98 &&;
+#X obj 444 97 &&;
+#X obj 263 73 >= 32;
+#X obj 300 73 < 64;
+#X obj 339 73 >= 64;
+#X obj 380 72 < 96;
+#X obj 428 71 >= 96;
+#X obj 465 71 < 128;
+#X floatatom 273 121 5 0 0 0 - - -;
+#X floatatom 354 119 5 0 0 0 - - -;
+#X floatatom 438 118 5 0 0 0 - - -;
+#X obj 273 148 * 2;
+#X obj 355 147 * 3;
+#X obj 436 147 * 4;
+#X obj 246 205 +;
+#X obj 398 200 +;
+#X obj 315 246 +;
+#X floatatom 105 352 5 0 0 0 - - -;
+#X floatatom 181 356 5 0 0 0 - - -;
+#X floatatom 246 356 5 0 0 0 - - -;
+#X floatatom 316 352 5 0 0 0 - - -;
+#X obj -125 824 outlet;
+#X obj 116 408 / 32;
+#X obj 181 408 / 32;
+#X obj 243 410 / 32;
+#X obj 316 408 / 32;
+#X obj 177 381 - 32;
+#X obj 245 382 - 64;
+#X obj 317 378 - 96;
+#X text 544 477 calc frac;
+#X obj 35 498 -;
+#X obj 35 479 float 1;
+#X obj 159 626 loadbang;
+#X obj -134 764 + 0;
+#X floatatom 85 526 5 0 0 0 - - -;
+#X floatatom 36 527 5 0 0 0 - - -;
+#X obj -150 736 * 0.1;
+#X obj -113 736 * 0.15;
+#X obj -42 760 + 0;
+#X obj -58 732 * 0.1;
+#X obj -21 732 * 0.15;
+#X obj 45 761 + 0;
+#X obj 138 762 + 0;
+#X obj 153 506 -;
+#X obj 153 487 float 1;
+#X floatatom 200 526 5 0 0 0 - - -;
+#X floatatom 154 528 5 0 0 0 - - -;
+#X obj 286 502 -;
+#X obj 286 483 float 1;
+#X floatatom 335 526 5 0 0 0 - - -;
+#X floatatom 287 524 5 0 0 0 - - -;
+#X text 6 678 insert values at points here;
+#X obj 416 505 -;
+#X obj 416 486 float 1;
+#X floatatom 467 526 5 0 0 0 - - -;
+#X floatatom 417 527 5 0 0 0 - - -;
+#X obj 29 733 * 30;
+#X obj 66 733 * 60;
+#X obj 119 733 * 60;
+#X obj 159 734 * 90;
+#X obj -543 849 outlet;
+#X obj -557 676 loadbang;
+#X obj -552 789 + 0;
+#X obj -568 761 * 0.1;
+#X obj -531 761 * 0.15;
+#X obj -460 785 + 0;
+#X obj -476 757 * 0.1;
+#X obj -439 757 * 0.15;
+#X obj -373 786 + 0;
+#X obj -280 787 + 0;
+#X text -630 702 insert values at points here;
+#X obj -389 758 * 30;
+#X obj -352 758 * 60;
+#X obj -299 758 * 60;
+#X obj -259 759 * 90;
+#X text -541 827 comment;
+#X obj -543 728 float 0;
+#X obj -262 725 float 1;
+#X text -595 848 saw vol;
+#X text -207 825 pulse volume;
+#X obj -470 726 float 0;
+#X obj -402 728 float 1;
+#X obj -330 726 float 1;
+#X obj -125 703 float 0;
+#X obj -52 701 float 0;
+#X obj 16 703 float 0;
+#X obj 88 701 float 1;
+#X obj 157 701 float 1;
+#X obj 264 818 outlet;
+#X obj 548 620 loadbang;
+#X obj 255 758 + 0;
+#X obj 239 730 * 0.1;
+#X obj 276 730 * 0.15;
+#X obj 347 754 + 0;
+#X obj 331 726 * 0.1;
+#X obj 368 726 * 0.15;
+#X obj 434 755 + 0;
+#X obj 527 756 + 0;
+#X text 373 667 insert values at points here;
+#X obj 418 727 * 30;
+#X obj 455 727 * 60;
+#X obj 508 727 * 60;
+#X obj 548 728 * 90;
+#X text 182 819 pulse width;
+#X obj 677 819 outlet;
+#X obj 961 621 loadbang;
+#X obj 668 759 + 0;
+#X obj 652 731 * 0.1;
+#X obj 689 731 * 0.15;
+#X obj 760 755 + 0;
+#X obj 744 727 * 0.1;
+#X obj 781 727 * 0.15;
+#X obj 847 756 + 0;
+#X obj 940 757 + 0;
+#X text 682 664 insert values at points here;
+#X obj 831 728 * 30;
+#X obj 868 728 * 60;
+#X obj 921 728 * 60;
+#X obj 961 729 * 90;
+#X obj 397 174 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 315 224 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 246 175 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 255 28 t f f f f f f f f;
+#X obj 117 -57 t f f;
+#X obj 415 462 t b f f;
+#X obj 283 458 t b f f;
+#X obj 155 463 t b f f;
+#X obj 36 452 t b f f;
+#X text 266 796 comment;
+#X text -124 801 comment;
+#X obj 959 696 float 0;
+#X text 595 820 sine volume;
+#X obj 677 698 float 1;
+#X obj 750 696 float 1;
+#X obj 818 698 float 0;
+#X obj 891 696 float 0;
+#X obj 477 695 float 0.5;
+#X obj 405 697 float 0.5;
+#X obj 337 695 float 0.5;
+#X obj 264 697 float 0.5;
+#X obj 166 308 route 1 2 3 4;
+#X obj 164 281 pack;
+#X obj 546 695 float 0.01;
+#X connect 0 0 130 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 4 0 21 0;
+#X connect 5 0 3 0;
+#X connect 6 0 15 0;
+#X connect 7 0 16 0;
+#X connect 8 0 17 0;
+#X connect 9 0 6 0;
+#X connect 10 0 6 1;
+#X connect 11 0 7 0;
+#X connect 12 0 7 1;
+#X connect 13 0 8 0;
+#X connect 14 0 8 1;
+#X connect 15 0 18 0;
+#X connect 16 0 19 0;
+#X connect 17 0 20 0;
+#X connect 18 0 21 1;
+#X connect 18 0 128 0;
+#X connect 19 0 22 0;
+#X connect 20 0 22 1;
+#X connect 20 0 126 0;
+#X connect 21 0 23 0;
+#X connect 22 0 23 1;
+#X connect 22 0 127 0;
+#X connect 23 0 148 0;
+#X connect 24 0 29 0;
+#X connect 25 0 33 0;
+#X connect 26 0 34 0;
+#X connect 27 0 35 0;
+#X connect 29 0 134 0;
+#X connect 30 0 133 0;
+#X connect 31 0 132 0;
+#X connect 32 0 131 0;
+#X connect 33 0 30 0;
+#X connect 34 0 31 0;
+#X connect 35 0 32 0;
+#X connect 37 0 42 0;
+#X connect 38 0 37 0;
+#X connect 39 0 90 0;
+#X connect 39 0 91 0;
+#X connect 39 0 92 0;
+#X connect 39 0 93 0;
+#X connect 39 0 94 0;
+#X connect 40 0 28 0;
+#X connect 41 0 44 0;
+#X connect 41 0 71 0;
+#X connect 41 0 99 0;
+#X connect 41 0 115 0;
+#X connect 42 0 43 0;
+#X connect 42 0 70 0;
+#X connect 42 0 98 0;
+#X connect 42 0 114 0;
+#X connect 43 0 40 0;
+#X connect 44 0 40 1;
+#X connect 45 0 28 0;
+#X connect 46 0 45 0;
+#X connect 47 0 45 1;
+#X connect 48 0 28 0;
+#X connect 49 0 28 0;
+#X connect 50 0 53 0;
+#X connect 51 0 50 0;
+#X connect 52 0 47 0;
+#X connect 52 0 74 0;
+#X connect 52 0 102 0;
+#X connect 52 0 118 0;
+#X connect 53 0 46 0;
+#X connect 53 0 73 0;
+#X connect 53 0 101 0;
+#X connect 53 0 117 0;
+#X connect 54 0 57 0;
+#X connect 55 0 54 0;
+#X connect 56 0 64 0;
+#X connect 56 0 79 0;
+#X connect 56 0 107 0;
+#X connect 56 0 123 0;
+#X connect 57 0 63 0;
+#X connect 57 0 78 0;
+#X connect 57 0 106 0;
+#X connect 57 0 122 0;
+#X connect 59 0 62 0;
+#X connect 60 0 59 0;
+#X connect 61 0 66 0;
+#X connect 61 0 81 0;
+#X connect 61 0 109 0;
+#X connect 61 0 125 0;
+#X connect 62 0 65 0;
+#X connect 62 0 80 0;
+#X connect 62 0 108 0;
+#X connect 62 0 124 0;
+#X connect 63 0 48 0;
+#X connect 64 0 48 1;
+#X connect 65 0 49 0;
+#X connect 66 0 49 1;
+#X connect 68 0 83 0;
+#X connect 68 0 84 0;
+#X connect 68 0 87 0;
+#X connect 68 0 88 0;
+#X connect 68 0 89 0;
+#X connect 69 0 67 0;
+#X connect 70 0 69 0;
+#X connect 71 0 69 1;
+#X connect 72 0 67 0;
+#X connect 73 0 72 0;
+#X connect 74 0 72 1;
+#X connect 75 0 67 0;
+#X connect 76 0 67 0;
+#X connect 78 0 75 0;
+#X connect 79 0 75 1;
+#X connect 80 0 76 0;
+#X connect 81 0 76 1;
+#X connect 83 0 70 1;
+#X connect 84 0 81 1;
+#X connect 87 0 71 1;
+#X connect 87 0 73 1;
+#X connect 88 0 74 1;
+#X connect 88 0 78 1;
+#X connect 89 0 79 1;
+#X connect 89 0 80 1;
+#X connect 90 0 43 1;
+#X connect 91 0 44 1;
+#X connect 91 0 46 1;
+#X connect 92 0 47 1;
+#X connect 92 0 63 1;
+#X connect 93 0 64 1;
+#X connect 93 0 65 1;
+#X connect 94 0 66 1;
+#X connect 96 0 143 0;
+#X connect 96 0 144 0;
+#X connect 96 0 145 0;
+#X connect 96 0 146 0;
+#X connect 96 0 149 0;
+#X connect 97 0 95 0;
+#X connect 98 0 97 0;
+#X connect 99 0 97 1;
+#X connect 100 0 95 0;
+#X connect 101 0 100 0;
+#X connect 102 0 100 1;
+#X connect 103 0 95 0;
+#X connect 104 0 95 0;
+#X connect 106 0 103 0;
+#X connect 107 0 103 1;
+#X connect 108 0 104 0;
+#X connect 109 0 104 1;
+#X connect 112 0 137 0;
+#X connect 112 0 139 0;
+#X connect 112 0 140 0;
+#X connect 112 0 141 0;
+#X connect 112 0 142 0;
+#X connect 113 0 111 0;
+#X connect 114 0 113 0;
+#X connect 115 0 113 1;
+#X connect 116 0 111 0;
+#X connect 117 0 116 0;
+#X connect 118 0 116 1;
+#X connect 119 0 111 0;
+#X connect 120 0 111 0;
+#X connect 122 0 119 0;
+#X connect 123 0 119 1;
+#X connect 124 0 120 0;
+#X connect 125 0 120 1;
+#X connect 126 0 22 0;
+#X connect 127 0 23 0;
+#X connect 128 0 21 0;
+#X connect 129 0 5 0;
+#X connect 129 1 2 0;
+#X connect 129 2 9 0;
+#X connect 129 3 10 0;
+#X connect 129 4 11 0;
+#X connect 129 5 12 0;
+#X connect 129 6 13 0;
+#X connect 129 7 14 0;
+#X connect 130 0 129 0;
+#X connect 130 1 148 1;
+#X connect 131 0 60 0;
+#X connect 131 1 59 1;
+#X connect 131 2 61 0;
+#X connect 132 0 55 0;
+#X connect 132 1 54 1;
+#X connect 132 2 56 0;
+#X connect 133 0 51 0;
+#X connect 133 1 50 1;
+#X connect 133 2 52 0;
+#X connect 134 0 38 0;
+#X connect 134 1 37 1;
+#X connect 134 2 41 0;
+#X connect 137 0 125 1;
+#X connect 139 0 114 1;
+#X connect 140 0 115 1;
+#X connect 140 0 117 1;
+#X connect 141 0 118 1;
+#X connect 141 0 122 1;
+#X connect 142 0 123 1;
+#X connect 142 0 124 1;
+#X connect 143 0 107 1;
+#X connect 143 0 108 1;
+#X connect 144 0 102 1;
+#X connect 144 0 106 1;
+#X connect 145 0 99 1;
+#X connect 145 0 101 1;
+#X connect 146 0 98 1;
+#X connect 147 0 24 0;
+#X connect 147 1 25 0;
+#X connect 147 2 26 0;
+#X connect 147 3 27 0;
+#X connect 148 0 147 0;
+#X connect 149 0 109 1;
+#X restore 44 163 pd interpolatorWave;
+#X connect 0 0 16 0;
+#X connect 0 0 37 0;
+#X connect 1 0 4 0;
+#X connect 1 0 29 1;
+#X connect 4 0 7 0;
+#X connect 6 0 12 0;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 8 0 19 0;
+#X connect 10 0 4 0;
+#X connect 11 0 10 0;
+#X connect 12 0 27 0;
+#X connect 14 0 17 0;
+#X connect 15 0 26 0;
+#X connect 16 0 15 0;
+#X connect 17 0 3 0;
+#X connect 18 0 33 0;
+#X connect 19 0 18 0;
+#X connect 20 0 8 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 30 0;
+#X connect 24 0 25 0;
+#X connect 25 0 28 0;
+#X connect 26 0 14 1;
+#X connect 27 0 3 0;
+#X connect 28 0 18 1;
+#X connect 29 0 20 0;
+#X connect 30 0 29 0;
+#X connect 32 0 23 0;
+#X connect 32 1 28 0;
+#X connect 33 0 6 1;
+#X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 36 0 33 1;
+#X connect 37 0 14 0;
+#X connect 38 0 54 0;
+#X connect 39 0 54 0;
+#X connect 41 0 37 1;
+#X connect 42 0 26 1;
+#X connect 43 0 16 1;
+#X connect 44 0 27 1;
+#X connect 45 0 48 0;
+#X connect 46 0 49 0;
+#X connect 47 0 50 0;
+#X connect 48 0 38 0;
+#X connect 49 0 38 0;
+#X connect 50 0 38 0;
+#X connect 54 0 41 0;
+#X connect 54 1 42 0;
+#X connect 54 2 43 0;
+#X connect 54 3 44 0;
+#X restore 76 221 pd oscillator;
+#N canvas 42 77 1074 773 filter 0;
+#X obj 44 22 inlet~;
+#X obj 165 84 route filtFreq;
+#X obj 855 112 route reson;
+#X obj 99 639 outlet~;
+#X obj 169 306 mtof~;
+#X obj 167 43 route list;
+#X obj 165 11 r fromOF;
+#X obj 316 19 inlet~;
+#X text 362 19 envelope;
+#X obj 171 189 sig~;
+#X obj 174 250 +~;
+#X obj 662 265 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 565 230 filetr freq;
+#X text 645 226 resonance;
+#X floatatom 822 416 5 0 0 0 - - -;
+#X msg 363 391 \$1 100;
+#X obj 363 415 line~;
+#X obj 407 303 hsl 128 15 0 1 0 1 empty empty empty -2 -8 0 10 -262144
+-1 -1 5600 1;
+#X text 284 273 Mode: 0 = lowpass \, 0.5 = resonant bandpass \, 1 =
+highpass;
+#X floatatom 403 356 5 0 0 0 - - -;
+#X obj 820 389 - 3;
+#X obj 820 472 + 100;
+#X obj 820 496 dbtorms;
+#X floatatom 820 525 5 0 0 0 - - -;
+#X obj 820 443 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262144 -1 -1 -0.8 256;
+#X obj 364 149 route fType;
+#X obj 820 356 / 5;
+#X obj 98 558 multimode_libpd.mmb~;
+#X obj 99 598 biquad_libpd.mmb~;
+#X floatatom 659 420 5 0 0 0 - - -;
+#X obj 167 280 clip~ 20 128;
+#X obj 169 220 lop~ 50;
+#X obj 169 122 * 0.6;
+#X obj 172 158 + 30;
+#X obj 238 221 *~ 110;
+#X obj 882 28 r fromOF;
+#X obj 815 553 lop~ 50;
+#X obj 881 57 route list;
+#X obj 891 81 route smoothing;
+#X text 38 2 audio in;
+#X text 478 17 ftype;
+#X text 590 17 ffreq;
+#X obj 544 17 inlet;
+#X obj 432 17 inlet;
+#X obj 646 17 inlet;
+#X text 692 17 reson;
+#X floatatom 195 386 5 0 0 0 - - -;
+#X connect 0 0 28 0;
+#X connect 1 0 32 0;
+#X connect 2 0 26 0;
+#X connect 4 0 27 0;
+#X connect 5 0 1 0;
+#X connect 5 0 2 0;
+#X connect 5 0 25 0;
+#X connect 6 0 5 0;
+#X connect 7 0 34 0;
+#X connect 9 0 31 0;
+#X connect 10 0 30 0;
+#X connect 11 0 26 0;
+#X connect 11 0 29 0;
+#X connect 14 0 24 0;
+#X connect 15 0 16 0;
+#X connect 16 0 27 2;
+#X connect 17 0 19 0;
+#X connect 17 0 15 0;
+#X connect 20 0 14 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 36 0;
+#X connect 24 0 21 0;
+#X connect 25 0 15 0;
+#X connect 26 0 20 0;
+#X connect 27 0 28 1;
+#X connect 27 1 28 2;
+#X connect 27 2 28 3;
+#X connect 27 3 28 4;
+#X connect 27 4 28 5;
+#X connect 28 0 3 0;
+#X connect 30 0 4 0;
+#X connect 31 0 10 0;
+#X connect 32 0 33 0;
+#X connect 33 0 9 0;
+#X connect 34 0 10 1;
+#X connect 35 0 37 0;
+#X connect 36 0 27 1;
+#X connect 37 0 38 0;
+#X connect 38 0 36 1;
+#X connect 38 0 31 1;
+#X connect 42 0 32 0;
+#X connect 43 0 15 0;
+#X connect 44 0 26 0;
+#X restore 77 250 pd filter;
+#X obj 96 296 *~;
+#X obj 73 375 clip~ -1 1;
+#N canvas 525 162 1052 736 fenvelope 0;
+#X obj 113 33 inlet;
+#X text 162 27 tribber;
+#X obj 347 0 inlet;
+#X obj 216 137 * 123;
+#X obj 306 163 * 123;
+#X text 474 63 proportion of level that is allways on;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 308 134 * 6;
+#X obj 123 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 262 301 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 260 395 pack 0 1;
+#X obj 469 289 f 1;
+#X obj 239 225 + 1;
+#X obj 142 341 f 1;
+#X obj 253 368 f 0;
+#X obj 309 271 + 3;
+#X obj 134 680 outlet~;
+#X text 82 678 filter;
+#X obj 316 461 *~ 1;
+#X obj 303 368 f 125;
+#X obj 182 339 f 1;
+#X obj 330 559 *~ 1;
+#X obj 306 191 + 10;
+#X obj 404 0 inlet;
+#X text 345 -20 attack;
+#X text 406 -23 decay;
+#X obj 494 5 inlet;
+#X text 488 -16 duration;
+#X obj 262 330 t b b;
+#X obj 121 203 t b b b;
+#X connect 0 0 10 0;
+#X connect 2 0 3 0;
+#X connect 3 0 16 0;
+#X connect 4 0 26 0;
+#X connect 6 0 22 1;
+#X connect 7 0 15 0;
+#X connect 7 1 6 1;
+#X connect 8 0 7 0;
+#X connect 9 0 4 0;
+#X connect 10 0 33 0;
+#X connect 11 0 32 0;
+#X connect 12 0 22 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 6 0;
+#X connect 16 0 19 0;
+#X connect 16 0 24 1;
+#X connect 17 0 13 0;
+#X connect 18 0 14 0;
+#X connect 19 0 11 1;
+#X connect 22 0 25 0;
+#X connect 23 0 14 1;
+#X connect 24 0 13 1;
+#X connect 25 0 20 0;
+#X connect 26 0 23 1;
+#X connect 27 0 9 0;
+#X connect 30 0 3 1;
+#X connect 30 0 4 1;
+#X connect 32 0 18 0;
+#X connect 32 1 23 0;
+#X connect 33 0 17 0;
+#X connect 33 1 24 0;
+#X connect 33 2 11 0;
+#X restore 167 221 pd fenvelope;
+#N canvas 867 125 1052 736 aenvelope 0;
+#X obj 113 33 inlet;
+#X obj 539 46 inlet;
+#X obj 216 137 * 123;
+#X obj 341 162 * 123;
+#X obj 468 202 route sustain;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 343 133 * 6;
+#X obj 341 190 + 50;
+#X obj 113 186 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 270 303 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 271 381 pack 0 1;
+#X obj 257 645 clip~ -1 1;
+#X obj 312 580 dbtorms~;
+#X obj 254 682 outlet~;
+#X obj 469 289 f 1;
+#X obj 316 520 *~ 60;
+#X obj 316 547 +~ 40;
+#X obj 218 161 + 1;
+#X obj 142 341 f 1;
+#X obj 269 349 f 0;
+#X obj 309 271 + 3;
+#X text 318 681 amplitude;
+#X obj 316 461 *~ 1;
+#X obj 318 490 +~ 0;
+#X obj 319 348 f 125;
+#X obj 182 339 f 1;
+#X obj 296 608 lop~ 50;
+#X obj 484 511 r fromOF;
+#X obj 481 565 route smoothing;
+#X obj 483 538 route list;
+#X obj 224 49 inlet;
+#X obj 322 49 inlet;
+#X text 232 28 attack;
+#X text 330 28 decay;
+#X text 162 28 trigger;
+#X text 532 18 total time;
+#X obj 237 225 t f f;
+#X obj 102 243 t b b b;
+#X obj 280 325 t b b;
+#X connect 0 0 10 0;
+#X connect 1 0 2 1;
+#X connect 1 0 3 1;
+#X connect 2 0 21 0;
+#X connect 3 0 9 0;
+#X connect 4 0 7 0;
+#X connect 5 0 26 1;
+#X connect 6 0 18 0;
+#X connect 6 1 5 1;
+#X connect 7 0 6 0;
+#X connect 7 0 27 1;
+#X connect 8 0 3 0;
+#X connect 9 0 28 1;
+#X connect 10 0 41 0;
+#X connect 11 0 23 0;
+#X connect 11 0 42 0;
+#X connect 12 0 26 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 17 0;
+#X connect 16 0 30 0;
+#X connect 18 0 5 0;
+#X connect 19 0 20 0;
+#X connect 20 0 16 0;
+#X connect 21 0 40 0;
+#X connect 22 0 13 0;
+#X connect 23 0 14 0;
+#X connect 24 0 11 1;
+#X connect 26 0 27 0;
+#X connect 27 0 19 0;
+#X connect 28 0 14 1;
+#X connect 29 0 13 1;
+#X connect 30 0 15 0;
+#X connect 31 0 33 0;
+#X connect 32 0 30 1;
+#X connect 33 0 32 0;
+#X connect 34 0 2 0;
+#X connect 35 0 8 0;
+#X connect 40 0 29 1;
+#X connect 40 1 24 0;
+#X connect 41 0 22 0;
+#X connect 41 1 29 0;
+#X connect 41 2 11 0;
+#X connect 42 0 23 0;
+#X connect 42 1 28 0;
+#X restore 259 222 pd aenvelope;
+#N canvas 22 194 893 724 reverb 0;
+#X obj 44 173 *~;
+#X obj 351 160 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X floatatom 344 184 5 0 0 0 - - -;
+#X obj 342 206 * -1;
+#X obj 343 232 + 1;
+#X obj 149 167 *~;
+#X floatatom 490 281 5 0 0 0 - - -;
+#X obj 96 206 rev1~ 70;
+#X obj 158 208 rev1~ 68;
+#X obj 557 173 vsl 15 128 0 100 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 490 307 + 3;
+#X obj 408 70 r fromOF;
+#X obj 408 94 route list;
+#X obj 408 118 route revDryWet revLength;
+#X obj 76 370 outlet~;
+#X obj 141 369 outlet~;
+#X obj 73 80 inlet~;
+#X obj 262 41 inlet;
+#X obj 390 27 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#N canvas 861 22 993 1015 interpolatorReverb 0;
+#X obj 71 34 inlet;
+#X text 66 12 slider control;
+#X floatatom 105 352 5 0 0 0 - - -;
+#X floatatom 181 356 5 0 0 0 - - -;
+#X floatatom 246 356 5 0 0 0 - - -;
+#X floatatom 316 352 5 0 0 0 - - -;
+#X obj 530 652 float 0.1;
+#X text 60 827 rev mix;
+#X obj 530 773 outlet;
+#X text 532 751 rev dec time;
+#X obj 116 408 / 32;
+#X obj 181 408 / 32;
+#X obj 243 410 / 32;
+#X obj 316 408 / 32;
+#X obj 177 381 - 32;
+#X obj 245 382 - 64;
+#X obj 317 378 - 96;
+#X text 544 477 calc frac;
+#X obj 70 500 -;
+#X obj 70 481 float 1;
+#X obj 814 575 loadbang;
+#X obj 603 650 float 0.15;
+#X obj 521 713 + 0;
+#X floatatom 126 524 5 0 0 0 - - -;
+#X floatatom 71 529 5 0 0 0 - - -;
+#X obj 505 685 * 0.1;
+#X obj 542 685 * 0.15;
+#X obj 613 709 + 0;
+#X obj 597 681 * 0.1;
+#X obj 634 681 * 0.15;
+#X obj 700 710 + 0;
+#X obj 793 711 + 0;
+#X obj 181 502 -;
+#X obj 178 483 float 1;
+#X floatatom 241 523 5 0 0 0 - - -;
+#X floatatom 182 524 5 0 0 0 - - -;
+#X obj 289 504 -;
+#X obj 289 485 float 1;
+#X floatatom 345 524 5 0 0 0 - - -;
+#X floatatom 290 526 5 0 0 0 - - -;
+#X text 772 621 insert values at points here;
+#X obj 396 504 -;
+#X obj 396 485 float 1;
+#X floatatom 503 518 5 0 0 0 - - -;
+#X floatatom 397 526 5 0 0 0 - - -;
+#X obj 684 682 * 30;
+#X obj 721 682 * 60;
+#X obj 774 682 * 60;
+#X obj 814 683 * 90;
+#X obj 114 825 outlet;
+#X obj 251 643 loadbang;
+#X obj 106 754 + 0;
+#X obj 87 710 * 0.1;
+#X obj 124 710 * 0.15;
+#X obj 195 734 + 0;
+#X obj 179 706 * 0.1;
+#X obj 216 706 * 0.15;
+#X obj 282 735 + 0;
+#X obj 375 736 + 0;
+#X text 25 651 insert values at points here;
+#X obj 266 707 * 30;
+#X obj 303 707 * 60;
+#X obj 356 707 * 60;
+#X obj 396 708 * 90;
+#X text 114 776 comment;
+#X obj 112 677 float 0;
+#X obj 253 677 float 0.3;
+#X obj 325 675 float 0.6;
+#X obj 393 674 float 1;
+#X obj 185 675 float 0.02;
+#X obj 671 652 float 20;
+#X obj 812 650 float 65;
+#X obj 743 650 float 40;
+#X obj 174 93 < 32;
+#X obj 159 119 &&;
+#X floatatom 168 141 5 0 0 0 - - -;
+#X obj 143 93 >= 0;
+#X obj 236 118 &&;
+#X obj 316 117 &&;
+#X obj 401 116 &&;
+#X obj 220 92 >= 32;
+#X obj 257 92 < 64;
+#X obj 296 92 >= 64;
+#X obj 337 91 < 96;
+#X obj 385 90 >= 96;
+#X obj 422 90 < 128;
+#X floatatom 230 140 5 0 0 0 - - -;
+#X floatatom 311 138 5 0 0 0 - - -;
+#X floatatom 395 137 5 0 0 0 - - -;
+#X obj 230 167 * 2;
+#X obj 312 166 * 3;
+#X obj 393 166 * 4;
+#X obj 203 224 +;
+#X obj 355 219 +;
+#X obj 272 265 +;
+#X obj 354 193 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 272 243 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 203 194 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 212 47 t f f f f f f f f;
+#X obj 103 57 t f f;
+#X obj 394 457 t b f f;
+#X obj 288 457 t b f f;
+#X obj 178 454 t b f f;
+#X obj 74 450 t b f f;
+#X obj 166 311 route 1 2 3 4;
+#X obj 166 288 pack f f;
+#X connect 0 0 99 0;
+#X connect 2 0 10 0;
+#X connect 3 0 14 0;
+#X connect 4 0 15 0;
+#X connect 5 0 16 0;
+#X connect 6 0 25 1;
+#X connect 10 0 103 0;
+#X connect 11 0 102 0;
+#X connect 12 0 101 0;
+#X connect 13 0 100 0;
+#X connect 14 0 11 0;
+#X connect 15 0 12 0;
+#X connect 16 0 13 0;
+#X connect 18 0 24 0;
+#X connect 19 0 18 0;
+#X connect 20 0 6 0;
+#X connect 20 0 21 0;
+#X connect 20 0 70 0;
+#X connect 20 0 71 0;
+#X connect 20 0 72 0;
+#X connect 21 0 26 1;
+#X connect 21 0 28 1;
+#X connect 22 0 8 0;
+#X connect 23 0 26 0;
+#X connect 23 0 53 0;
+#X connect 24 0 25 0;
+#X connect 24 0 52 0;
+#X connect 25 0 22 0;
+#X connect 26 0 22 1;
+#X connect 27 0 8 0;
+#X connect 28 0 27 0;
+#X connect 29 0 27 1;
+#X connect 30 0 8 0;
+#X connect 31 0 8 0;
+#X connect 32 0 35 0;
+#X connect 33 0 32 0;
+#X connect 34 0 29 0;
+#X connect 34 0 56 0;
+#X connect 35 0 28 0;
+#X connect 35 0 55 0;
+#X connect 36 0 39 0;
+#X connect 37 0 36 0;
+#X connect 38 0 46 0;
+#X connect 38 0 61 0;
+#X connect 39 0 45 0;
+#X connect 39 0 60 0;
+#X connect 41 0 44 0;
+#X connect 42 0 41 0;
+#X connect 43 0 48 0;
+#X connect 43 0 63 0;
+#X connect 44 0 47 0;
+#X connect 44 0 62 0;
+#X connect 45 0 30 0;
+#X connect 46 0 30 1;
+#X connect 47 0 31 0;
+#X connect 48 0 31 1;
+#X connect 50 0 65 0;
+#X connect 50 0 66 0;
+#X connect 50 0 67 0;
+#X connect 50 0 68 0;
+#X connect 50 0 69 0;
+#X connect 51 0 49 0;
+#X connect 52 0 51 0;
+#X connect 53 0 51 1;
+#X connect 54 0 49 0;
+#X connect 55 0 54 0;
+#X connect 56 0 54 1;
+#X connect 57 0 49 0;
+#X connect 58 0 49 0;
+#X connect 60 0 57 0;
+#X connect 61 0 57 1;
+#X connect 62 0 58 0;
+#X connect 63 0 58 1;
+#X connect 65 0 52 1;
+#X connect 66 0 56 1;
+#X connect 66 0 60 1;
+#X connect 67 0 61 1;
+#X connect 67 0 62 1;
+#X connect 68 0 63 1;
+#X connect 69 0 53 1;
+#X connect 69 0 55 1;
+#X connect 70 0 29 1;
+#X connect 70 0 45 1;
+#X connect 71 0 48 1;
+#X connect 72 0 46 1;
+#X connect 72 0 47 1;
+#X connect 73 0 74 1;
+#X connect 74 0 75 0;
+#X connect 75 0 92 0;
+#X connect 76 0 74 0;
+#X connect 77 0 86 0;
+#X connect 78 0 87 0;
+#X connect 79 0 88 0;
+#X connect 80 0 77 0;
+#X connect 81 0 77 1;
+#X connect 82 0 78 0;
+#X connect 83 0 78 1;
+#X connect 84 0 79 0;
+#X connect 85 0 79 1;
+#X connect 86 0 89 0;
+#X connect 87 0 90 0;
+#X connect 88 0 91 0;
+#X connect 89 0 92 1;
+#X connect 89 0 97 0;
+#X connect 90 0 93 0;
+#X connect 91 0 93 1;
+#X connect 91 0 95 0;
+#X connect 92 0 94 0;
+#X connect 93 0 94 1;
+#X connect 93 0 96 0;
+#X connect 94 0 105 0;
+#X connect 95 0 93 0;
+#X connect 96 0 94 0;
+#X connect 97 0 92 0;
+#X connect 98 0 76 0;
+#X connect 98 1 73 0;
+#X connect 98 2 80 0;
+#X connect 98 3 81 0;
+#X connect 98 4 82 0;
+#X connect 98 5 83 0;
+#X connect 98 6 84 0;
+#X connect 98 7 85 0;
+#X connect 99 0 98 0;
+#X connect 99 1 105 1;
+#X connect 100 0 42 0;
+#X connect 100 1 41 1;
+#X connect 100 2 43 0;
+#X connect 101 0 37 0;
+#X connect 101 1 36 1;
+#X connect 101 2 38 0;
+#X connect 102 0 33 0;
+#X connect 102 1 32 1;
+#X connect 102 2 34 0;
+#X connect 103 0 19 0;
+#X connect 103 1 18 1;
+#X connect 103 2 23 0;
+#X connect 104 0 2 0;
+#X connect 104 1 3 0;
+#X connect 104 2 4 0;
+#X connect 104 3 5 0;
+#X connect 105 0 104 0;
+#X restore 249 115 pd interpolatorReverb;
+#X connect 0 0 14 0;
+#X connect 0 0 15 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 2 0 5 1;
+#X connect 3 0 4 0;
+#X connect 4 0 0 1;
+#X connect 5 0 7 0;
+#X connect 5 0 8 0;
+#X connect 6 0 7 1;
+#X connect 6 0 10 0;
+#X connect 7 0 14 0;
+#X connect 8 0 15 0;
+#X connect 9 0 6 0;
+#X connect 10 0 8 1;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 2 0;
+#X connect 13 1 6 0;
+#X connect 16 0 0 0;
+#X connect 16 0 5 0;
+#X connect 17 0 19 0;
+#X connect 18 0 19 0;
+#X connect 19 0 2 0;
+#X connect 19 1 6 0;
+#X restore 73 407 pd reverb;
+#X obj 664 -65 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 92 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 120 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 80 56 / 127;
+#X obj 119 57 / 127;
+#X text 81 -112 attack;
+#X text 124 -112 decay;
+#X obj -42 -77 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text -53 -112 pitch;
+#X text -7 -114 duration;
+#X obj 314 -85 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 346 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 301 53 / 127;
+#X text 299 -115 ftype;
+#X text 342 -115 ffreq;
+#X obj 380 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 381 -116 reson;
+#X obj 569 -88 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 562 -111 reverb;
+#X obj 344 82 +;
+#X floatatom 339 135 5 0 0 0 - - -;
+#X obj 92 335 *~ 0.1;
+#X obj 47 -81 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 35 -102 wavef;
+#X text 655 -95 trigger;
+#X obj -38 -168 route pitch;
+#X obj 44 -169 route waveform;
+#X obj 138 -169 route attack;
+#X obj 221 -171 route decay;
+#X obj 301 -170 route fType;
+#X obj 378 -167 route fFreq;
+#X obj 459 -169 route reson;
+#X obj 547 -172 route reverb;
+#X obj 636 -172 route trigger;
+#X obj 337 110 - 185;
+#X obj -42 102 + 30;
+#X obj -41 72 / 3;
+#X obj 83 467 outlet~;
+#X obj 143 466 outlet~;
+#X obj 659 -257 inlet;
+#X obj 181 -294 inlet;
+#X text 182 -83 TARGET SYNTH;
+#X text 182 -61 TARGET SYNTH;
+#X text 180 -34 TARGET SYNTH;
+#X text 178 -5 TARGET SYNTH;
+#X obj 255 465 random 127;
+#X obj 513 430 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 329 464 random 127;
+#X obj 401 463 random 127;
+#X obj 476 462 random 127;
+#X obj 551 462 random 127;
+#X obj 631 460 random 127;
+#X obj 708 460 random 127;
+#X obj 800 457 random 127;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 28 0;
+#X connect 3 0 6 0;
+#X connect 4 0 1 1;
+#X connect 5 0 2 1;
+#X connect 6 0 44 0;
+#X connect 6 1 45 0;
+#X connect 7 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 10 0;
+#X connect 9 0 11 0;
+#X connect 10 0 4 1;
+#X connect 10 0 5 1;
+#X connect 11 0 4 2;
+#X connect 11 0 5 2;
+#X connect 14 0 43 0;
+#X connect 17 0 19 0;
+#X connect 18 0 26 0;
+#X connect 19 0 1 2;
+#X connect 22 0 1 4;
+#X connect 24 0 6 1;
+#X connect 26 0 41 0;
+#X connect 28 0 3 0;
+#X connect 29 0 0 0;
+#X connect 32 0 14 0;
+#X connect 33 0 29 0;
+#X connect 34 0 8 0;
+#X connect 35 0 9 0;
+#X connect 36 0 17 0;
+#X connect 37 0 18 0;
+#X connect 38 0 22 0;
+#X connect 39 0 24 0;
+#X connect 40 0 7 0;
+#X connect 41 0 1 3;
+#X connect 41 0 27 0;
+#X connect 42 0 26 1;
+#X connect 42 0 0 1;
+#X connect 43 0 42 0;
+#X connect 46 0 7 0;
+#X connect 47 0 32 0;
+#X connect 47 0 33 0;
+#X connect 47 0 34 0;
+#X connect 47 0 35 0;
+#X connect 47 0 36 0;
+#X connect 47 0 37 0;
+#X connect 47 0 38 0;
+#X connect 47 0 39 0;
+#X connect 47 0 40 0;
+#X connect 53 0 52 0;
+#X connect 53 0 54 0;
+#X connect 53 0 55 0;
+#X connect 53 0 56 0;
+#X connect 53 0 57 0;
+#X connect 53 0 58 0;
+#X connect 53 0 59 0;
+#X connect 53 0 60 0;
+#X restore 237 -44 pd targetSynth;
+#N canvas 99 28 824 911 candidateSynth 0;
+#N canvas 76 137 871 723 oscillator 0;
+#X obj 83 269 phasor~;
+#X obj 430 -51 inlet;
+#X text 73 522 audio out;
+#X obj 79 501 outlet~;
+#X obj 402 171 mtof;
+#X text 292 -112 "pWidth" \, "sqVol" \, "sawVol" \, "sineVol" \, "FMAmt"
+;
+#X obj 321 233 +~;
+#X obj 402 193 sig~;
+#X floatatom 564 131 5 0 0 0 - - -;
+#X text 627 93 fm rfeq;
+#X obj 354 136 int 64;
+#X obj 353 113 loadbang;
+#X obj 262 398 osc~ 220;
+#X text 29 390 subtract out of phase one;
+#X obj 84 377 -~;
+#X obj 151 327 wrap~;
+#X obj 150 302 +~ 0.5;
+#X obj 83 437 -~ 0.5;
+#X obj 568 186 *~ 0;
+#X obj 562 156 osc~;
+#X obj 561 105 mtof;
+#X obj 731 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 723 64 / 127;
+#X obj 548 29 * 100;
+#X obj 765 -85 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 764 62 / 127;
+#X obj 152 354 *~ 0;
+#X obj 263 429 *~ 1;
+#X obj 616 129 * 3500;
+#X obj 559 81 +;
+#X obj 560 54 - 40;
+#X text 408 -73 pitch freq;
+#X obj 552 1 route FMFreq FMAmt;
+#X obj 564 218 lop~ 20;
+#X obj 680 172 r fromOF;
+#X obj 679 201 route list;
+#X obj 677 226 route smoothing;
+#X obj 84 346 *~ 1;
+#N canvas 584 22 1336 1017 interpolatorWave 0;
+#X obj 80 -91 inlet;
+#X text 75 -113 slider control;
+#X obj 217 74 < 32;
+#X obj 202 100 &&;
+#X floatatom 211 122 5 0 0 0 - - -;
+#X obj 186 74 >= 0;
+#X obj 279 99 &&;
+#X obj 359 98 &&;
+#X obj 444 97 &&;
+#X obj 263 73 >= 32;
+#X obj 300 73 < 64;
+#X obj 339 73 >= 64;
+#X obj 380 72 < 96;
+#X obj 428 71 >= 96;
+#X obj 465 71 < 128;
+#X floatatom 273 121 5 0 0 0 - - -;
+#X floatatom 354 119 5 0 0 0 - - -;
+#X floatatom 438 118 5 0 0 0 - - -;
+#X obj 273 148 * 2;
+#X obj 355 147 * 3;
+#X obj 436 147 * 4;
+#X obj 246 205 +;
+#X obj 398 200 +;
+#X obj 315 246 +;
+#X floatatom 105 352 5 0 0 0 - - -;
+#X floatatom 181 356 5 0 0 0 - - -;
+#X floatatom 246 356 5 0 0 0 - - -;
+#X floatatom 316 352 5 0 0 0 - - -;
+#X obj -125 824 outlet;
+#X obj 116 408 / 32;
+#X obj 181 408 / 32;
+#X obj 243 410 / 32;
+#X obj 316 408 / 32;
+#X obj 177 381 - 32;
+#X obj 245 382 - 64;
+#X obj 317 378 - 96;
+#X text 544 477 calc frac;
+#X obj 35 498 -;
+#X obj 35 479 float 1;
+#X obj 159 626 loadbang;
+#X obj -134 764 + 0;
+#X floatatom 85 526 5 0 0 0 - - -;
+#X floatatom 36 527 5 0 0 0 - - -;
+#X obj -150 736 * 0.1;
+#X obj -113 736 * 0.15;
+#X obj -42 760 + 0;
+#X obj -58 732 * 0.1;
+#X obj -21 732 * 0.15;
+#X obj 45 761 + 0;
+#X obj 138 762 + 0;
+#X obj 153 506 -;
+#X obj 153 487 float 1;
+#X floatatom 200 526 5 0 0 0 - - -;
+#X floatatom 154 528 5 0 0 0 - - -;
+#X obj 286 502 -;
+#X obj 286 483 float 1;
+#X floatatom 335 526 5 0 0 0 - - -;
+#X floatatom 287 524 5 0 0 0 - - -;
+#X text 6 678 insert values at points here;
+#X obj 416 505 -;
+#X obj 416 486 float 1;
+#X floatatom 467 526 5 0 0 0 - - -;
+#X floatatom 417 527 5 0 0 0 - - -;
+#X obj 29 733 * 30;
+#X obj 66 733 * 60;
+#X obj 119 733 * 60;
+#X obj 159 734 * 90;
+#X obj -543 849 outlet;
+#X obj -557 676 loadbang;
+#X obj -552 789 + 0;
+#X obj -568 761 * 0.1;
+#X obj -531 761 * 0.15;
+#X obj -460 785 + 0;
+#X obj -476 757 * 0.1;
+#X obj -439 757 * 0.15;
+#X obj -373 786 + 0;
+#X obj -280 787 + 0;
+#X text -630 702 insert values at points here;
+#X obj -389 758 * 30;
+#X obj -352 758 * 60;
+#X obj -299 758 * 60;
+#X obj -259 759 * 90;
+#X text -541 827 comment;
+#X obj -543 728 float 0;
+#X obj -262 725 float 1;
+#X text -595 848 saw vol;
+#X text -207 825 pulse volume;
+#X obj -470 726 float 0;
+#X obj -402 728 float 1;
+#X obj -330 726 float 1;
+#X obj -125 703 float 0;
+#X obj -52 701 float 0;
+#X obj 16 703 float 0;
+#X obj 88 701 float 1;
+#X obj 157 701 float 1;
+#X obj 264 818 outlet;
+#X obj 548 620 loadbang;
+#X obj 255 758 + 0;
+#X obj 239 730 * 0.1;
+#X obj 276 730 * 0.15;
+#X obj 347 754 + 0;
+#X obj 331 726 * 0.1;
+#X obj 368 726 * 0.15;
+#X obj 434 755 + 0;
+#X obj 527 756 + 0;
+#X text 373 667 insert values at points here;
+#X obj 418 727 * 30;
+#X obj 455 727 * 60;
+#X obj 508 727 * 60;
+#X obj 548 728 * 90;
+#X text 182 819 pulse width;
+#X obj 546 695 float 0.1;
+#X obj 677 819 outlet;
+#X obj 961 621 loadbang;
+#X obj 668 759 + 0;
+#X obj 652 731 * 0.1;
+#X obj 689 731 * 0.15;
+#X obj 760 755 + 0;
+#X obj 744 727 * 0.1;
+#X obj 781 727 * 0.15;
+#X obj 847 756 + 0;
+#X obj 940 757 + 0;
+#X text 682 664 insert values at points here;
+#X obj 831 728 * 30;
+#X obj 868 728 * 60;
+#X obj 921 728 * 60;
+#X obj 961 729 * 90;
+#X obj 397 174 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 315 224 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 246 175 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 255 28 t f f f f f f f f;
+#X obj 117 -57 t f f;
+#X obj 415 462 t b f f;
+#X obj 283 458 t b f f;
+#X obj 155 463 t b f f;
+#X obj 36 452 t b f f;
+#X text 266 796 comment;
+#X text -124 801 comment;
+#X obj 959 696 float 0;
+#X text 595 820 sine volume;
+#X obj 677 698 float 1;
+#X obj 750 696 float 1;
+#X obj 818 698 float 0;
+#X obj 891 696 float 0;
+#X obj 477 695 float 0.5;
+#X obj 405 697 float 0.5;
+#X obj 337 695 float 0.5;
+#X obj 264 697 float 0.5;
+#X obj 166 308 route 1 2 3 4;
+#X obj 164 281 pack;
+#X connect 0 0 131 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 4 0 21 0;
+#X connect 5 0 3 0;
+#X connect 6 0 15 0;
+#X connect 7 0 16 0;
+#X connect 8 0 17 0;
+#X connect 9 0 6 0;
+#X connect 10 0 6 1;
+#X connect 11 0 7 0;
+#X connect 12 0 7 1;
+#X connect 13 0 8 0;
+#X connect 14 0 8 1;
+#X connect 15 0 18 0;
+#X connect 16 0 19 0;
+#X connect 17 0 20 0;
+#X connect 18 0 21 1;
+#X connect 18 0 129 0;
+#X connect 19 0 22 0;
+#X connect 20 0 22 1;
+#X connect 20 0 127 0;
+#X connect 21 0 23 0;
+#X connect 22 0 23 1;
+#X connect 22 0 128 0;
+#X connect 23 0 149 0;
+#X connect 24 0 29 0;
+#X connect 25 0 33 0;
+#X connect 26 0 34 0;
+#X connect 27 0 35 0;
+#X connect 29 0 135 0;
+#X connect 30 0 134 0;
+#X connect 31 0 133 0;
+#X connect 32 0 132 0;
+#X connect 33 0 30 0;
+#X connect 34 0 31 0;
+#X connect 35 0 32 0;
+#X connect 37 0 42 0;
+#X connect 38 0 37 0;
+#X connect 39 0 90 0;
+#X connect 39 0 91 0;
+#X connect 39 0 92 0;
+#X connect 39 0 93 0;
+#X connect 39 0 94 0;
+#X connect 40 0 28 0;
+#X connect 41 0 44 0;
+#X connect 41 0 71 0;
+#X connect 41 0 99 0;
+#X connect 41 0 116 0;
+#X connect 42 0 43 0;
+#X connect 42 0 70 0;
+#X connect 42 0 98 0;
+#X connect 42 0 115 0;
+#X connect 43 0 40 0;
+#X connect 44 0 40 1;
+#X connect 45 0 28 0;
+#X connect 46 0 45 0;
+#X connect 47 0 45 1;
+#X connect 48 0 28 0;
+#X connect 49 0 28 0;
+#X connect 50 0 53 0;
+#X connect 51 0 50 0;
+#X connect 52 0 47 0;
+#X connect 52 0 74 0;
+#X connect 52 0 102 0;
+#X connect 52 0 119 0;
+#X connect 53 0 46 0;
+#X connect 53 0 73 0;
+#X connect 53 0 101 0;
+#X connect 53 0 118 0;
+#X connect 54 0 57 0;
+#X connect 55 0 54 0;
+#X connect 56 0 64 0;
+#X connect 56 0 79 0;
+#X connect 56 0 107 0;
+#X connect 56 0 124 0;
+#X connect 57 0 63 0;
+#X connect 57 0 78 0;
+#X connect 57 0 106 0;
+#X connect 57 0 123 0;
+#X connect 59 0 62 0;
+#X connect 60 0 59 0;
+#X connect 61 0 66 0;
+#X connect 61 0 81 0;
+#X connect 61 0 109 0;
+#X connect 61 0 126 0;
+#X connect 62 0 65 0;
+#X connect 62 0 80 0;
+#X connect 62 0 108 0;
+#X connect 62 0 125 0;
+#X connect 63 0 48 0;
+#X connect 64 0 48 1;
+#X connect 65 0 49 0;
+#X connect 66 0 49 1;
+#X connect 68 0 83 0;
+#X connect 68 0 84 0;
+#X connect 68 0 87 0;
+#X connect 68 0 88 0;
+#X connect 68 0 89 0;
+#X connect 69 0 67 0;
+#X connect 70 0 69 0;
+#X connect 71 0 69 1;
+#X connect 72 0 67 0;
+#X connect 73 0 72 0;
+#X connect 74 0 72 1;
+#X connect 75 0 67 0;
+#X connect 76 0 67 0;
+#X connect 78 0 75 0;
+#X connect 79 0 75 1;
+#X connect 80 0 76 0;
+#X connect 81 0 76 1;
+#X connect 83 0 70 1;
+#X connect 84 0 81 1;
+#X connect 87 0 71 1;
+#X connect 87 0 73 1;
+#X connect 88 0 74 1;
+#X connect 88 0 78 1;
+#X connect 89 0 79 1;
+#X connect 89 0 80 1;
+#X connect 90 0 43 1;
+#X connect 91 0 44 1;
+#X connect 91 0 46 1;
+#X connect 92 0 47 1;
+#X connect 92 0 63 1;
+#X connect 93 0 64 1;
+#X connect 93 0 65 1;
+#X connect 94 0 66 1;
+#X connect 96 0 111 0;
+#X connect 96 0 144 0;
+#X connect 96 0 145 0;
+#X connect 96 0 146 0;
+#X connect 96 0 147 0;
+#X connect 97 0 95 0;
+#X connect 98 0 97 0;
+#X connect 99 0 97 1;
+#X connect 100 0 95 0;
+#X connect 101 0 100 0;
+#X connect 102 0 100 1;
+#X connect 103 0 95 0;
+#X connect 104 0 95 0;
+#X connect 106 0 103 0;
+#X connect 107 0 103 1;
+#X connect 108 0 104 0;
+#X connect 109 0 104 1;
+#X connect 111 0 109 1;
+#X connect 113 0 138 0;
+#X connect 113 0 140 0;
+#X connect 113 0 141 0;
+#X connect 113 0 142 0;
+#X connect 113 0 143 0;
+#X connect 114 0 112 0;
+#X connect 115 0 114 0;
+#X connect 116 0 114 1;
+#X connect 117 0 112 0;
+#X connect 118 0 117 0;
+#X connect 119 0 117 1;
+#X connect 120 0 112 0;
+#X connect 121 0 112 0;
+#X connect 123 0 120 0;
+#X connect 124 0 120 1;
+#X connect 125 0 121 0;
+#X connect 126 0 121 1;
+#X connect 127 0 22 0;
+#X connect 128 0 23 0;
+#X connect 129 0 21 0;
+#X connect 130 0 5 0;
+#X connect 130 1 2 0;
+#X connect 130 2 9 0;
+#X connect 130 3 10 0;
+#X connect 130 4 11 0;
+#X connect 130 5 12 0;
+#X connect 130 6 13 0;
+#X connect 130 7 14 0;
+#X connect 131 0 130 0;
+#X connect 131 1 149 1;
+#X connect 132 0 60 0;
+#X connect 132 1 59 1;
+#X connect 132 2 61 0;
+#X connect 133 0 55 0;
+#X connect 133 1 54 1;
+#X connect 133 2 56 0;
+#X connect 134 0 51 0;
+#X connect 134 1 50 1;
+#X connect 134 2 52 0;
+#X connect 135 0 38 0;
+#X connect 135 1 37 1;
+#X connect 135 2 41 0;
+#X connect 138 0 126 1;
+#X connect 140 0 115 1;
+#X connect 141 0 116 1;
+#X connect 141 0 118 1;
+#X connect 142 0 119 1;
+#X connect 142 0 123 1;
+#X connect 143 0 124 1;
+#X connect 143 0 125 1;
+#X connect 144 0 107 1;
+#X connect 144 0 108 1;
+#X connect 145 0 102 1;
+#X connect 145 0 106 1;
+#X connect 146 0 99 1;
+#X connect 146 0 101 1;
+#X connect 147 0 98 1;
+#X connect 148 0 24 0;
+#X connect 148 1 25 0;
+#X connect 148 2 26 0;
+#X connect 148 3 27 0;
+#X connect 149 0 148 0;
+#X restore 51 166 pd interpolatorWave;
+#X obj 62 124 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X obj 16 122 inlet;
+#X text 52 93 waveform;
+#X floatatom 42 198 5 0 0 0 - - -;
+#X floatatom 93 201 5 0 0 0 - - -;
+#X floatatom 141 205 5 0 0 0 - - -;
+#X floatatom 190 203 5 0 0 0 - - -;
+#X obj 29 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 101 -16 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 170 -14 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 31 19 float 10;
+#X obj 103 19 float 64;
+#X obj 173 21 float 120;
+#X text 192 219 sineVol;
+#X text 30 218 saw vol;
+#X text 92 221 sq vol;
+#X connect 0 0 16 0;
+#X connect 0 0 37 0;
+#X connect 1 0 4 0;
+#X connect 1 0 29 1;
+#X connect 4 0 7 0;
+#X connect 6 0 12 0;
+#X connect 6 0 0 0;
+#X connect 7 0 6 0;
+#X connect 8 0 19 0;
+#X connect 10 0 4 0;
+#X connect 11 0 10 0;
+#X connect 12 0 27 0;
+#X connect 14 0 17 0;
+#X connect 15 0 26 0;
+#X connect 16 0 15 0;
+#X connect 17 0 3 0;
+#X connect 18 0 33 0;
+#X connect 19 0 18 0;
+#X connect 20 0 8 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 30 0;
+#X connect 24 0 25 0;
+#X connect 25 0 28 0;
+#X connect 26 0 14 1;
+#X connect 27 0 3 0;
+#X connect 28 0 18 1;
+#X connect 29 0 20 0;
+#X connect 30 0 29 0;
+#X connect 32 0 23 0;
+#X connect 32 1 28 0;
+#X connect 33 0 6 1;
+#X connect 34 0 35 0;
+#X connect 35 0 36 0;
+#X connect 36 0 33 1;
+#X connect 37 0 14 0;
+#X connect 38 0 42 0;
+#X connect 38 1 43 0;
+#X connect 38 2 44 0;
+#X connect 38 3 45 0;
+#X connect 39 0 38 0;
+#X connect 40 0 38 0;
+#X connect 42 0 37 1;
+#X connect 43 0 26 1;
+#X connect 44 0 16 1;
+#X connect 45 0 27 1;
+#X connect 46 0 49 0;
+#X connect 47 0 50 0;
+#X connect 48 0 51 0;
+#X connect 49 0 39 0;
+#X connect 50 0 39 0;
+#X connect 51 0 39 0;
+#X restore 76 221 pd oscillator;
+#N canvas 42 77 1074 773 filter 0;
+#X obj 44 22 inlet~;
+#X obj 165 84 route filtFreq;
+#X obj 855 112 route reson;
+#X obj 99 639 outlet~;
+#X obj 169 306 mtof~;
+#X obj 167 43 route list;
+#X obj 165 11 r fromOF;
+#X obj 316 19 inlet~;
+#X text 362 19 envelope;
+#X obj 171 189 sig~;
+#X obj 174 250 +~;
+#X obj 662 265 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 565 230 filetr freq;
+#X text 645 226 resonance;
+#X floatatom 822 416 5 0 0 0 - - -;
+#X msg 363 391 \$1 100;
+#X obj 363 415 line~;
+#X obj 407 303 hsl 128 15 0 1 0 1 empty empty empty -2 -8 0 10 -262144
+-1 -1 5600 1;
+#X text 284 273 Mode: 0 = lowpass \, 0.5 = resonant bandpass \, 1 =
+highpass;
+#X floatatom 403 356 5 0 0 0 - - -;
+#X obj 820 389 - 3;
+#X obj 820 472 + 100;
+#X obj 820 496 dbtorms;
+#X floatatom 820 525 5 0 0 0 - - -;
+#X obj 820 443 nbx 5 14 -1e+37 1e+37 0 1 empty empty empty 0 -8 0 10
+-262144 -1 -1 2 256;
+#X obj 364 149 route fType;
+#X obj 820 356 / 5;
+#X obj 98 558 multimode_libpd.mmb~;
+#X obj 99 598 biquad_libpd.mmb~;
+#X floatatom 659 420 5 0 0 0 - - -;
+#X obj 167 280 clip~ 20 128;
+#X obj 169 220 lop~ 50;
+#X obj 169 122 * 0.6;
+#X obj 172 158 + 30;
+#X obj 238 221 *~ 110;
+#X obj 882 28 r fromOF;
+#X obj 815 553 lop~ 50;
+#X obj 881 57 route list;
+#X obj 891 81 route smoothing;
+#X text 38 2 audio in;
+#X text 478 17 ftype;
+#X text 590 17 ffreq;
+#X obj 544 17 inlet;
+#X obj 432 17 inlet;
+#X obj 646 17 inlet;
+#X text 692 17 reson;
+#X floatatom 195 386 5 0 0 0 - - -;
+#X connect 0 0 28 0;
+#X connect 1 0 32 0;
+#X connect 2 0 26 0;
+#X connect 4 0 27 0;
+#X connect 5 0 1 0;
+#X connect 5 0 2 0;
+#X connect 5 0 25 0;
+#X connect 6 0 5 0;
+#X connect 7 0 34 0;
+#X connect 9 0 31 0;
+#X connect 10 0 30 0;
+#X connect 11 0 26 0;
+#X connect 11 0 29 0;
+#X connect 14 0 24 0;
+#X connect 15 0 16 0;
+#X connect 16 0 27 2;
+#X connect 17 0 19 0;
+#X connect 17 0 15 0;
+#X connect 20 0 14 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 36 0;
+#X connect 24 0 21 0;
+#X connect 25 0 15 0;
+#X connect 26 0 20 0;
+#X connect 27 0 28 1;
+#X connect 27 1 28 2;
+#X connect 27 2 28 3;
+#X connect 27 3 28 4;
+#X connect 27 4 28 5;
+#X connect 28 0 3 0;
+#X connect 30 0 4 0;
+#X connect 31 0 10 0;
+#X connect 32 0 33 0;
+#X connect 33 0 9 0;
+#X connect 34 0 10 1;
+#X connect 35 0 37 0;
+#X connect 36 0 27 1;
+#X connect 37 0 38 0;
+#X connect 38 0 36 1;
+#X connect 38 0 31 1;
+#X connect 42 0 32 0;
+#X connect 43 0 15 0;
+#X connect 44 0 26 0;
+#X restore 77 250 pd filter;
+#X obj 96 296 *~;
+#X obj 73 375 clip~ -1 1;
+#N canvas 525 162 1052 736 fenvelope 0;
+#X obj 113 33 inlet;
+#X text 162 27 tribber;
+#X obj 347 0 inlet;
+#X obj 216 137 * 123;
+#X obj 306 163 * 123;
+#X text 474 63 proportion of level that is allways on;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 308 134 * 6;
+#X obj 123 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 262 301 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 260 395 pack 0 1;
+#X obj 469 289 f 1;
+#X obj 239 225 + 1;
+#X obj 142 341 f 1;
+#X obj 253 368 f 0;
+#X obj 309 271 + 3;
+#X obj 134 680 outlet~;
+#X text 82 678 filter;
+#X obj 316 461 *~ 1;
+#X obj 303 368 f 125;
+#X obj 182 339 f 1;
+#X obj 330 559 *~ 1;
+#X obj 306 191 + 10;
+#X obj 404 0 inlet;
+#X text 345 -20 attack;
+#X text 406 -23 decay;
+#X obj 494 5 inlet;
+#X text 488 -16 duration;
+#X obj 262 330 t b b;
+#X obj 121 203 t b b b;
+#X connect 0 0 10 0;
+#X connect 2 0 3 0;
+#X connect 3 0 16 0;
+#X connect 4 0 26 0;
+#X connect 6 0 22 1;
+#X connect 7 0 15 0;
+#X connect 7 1 6 1;
+#X connect 8 0 7 0;
+#X connect 9 0 4 0;
+#X connect 10 0 33 0;
+#X connect 11 0 32 0;
+#X connect 12 0 22 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 6 0;
+#X connect 16 0 19 0;
+#X connect 16 0 24 1;
+#X connect 17 0 13 0;
+#X connect 18 0 14 0;
+#X connect 19 0 11 1;
+#X connect 22 0 25 0;
+#X connect 23 0 14 1;
+#X connect 24 0 13 1;
+#X connect 25 0 20 0;
+#X connect 26 0 23 1;
+#X connect 27 0 9 0;
+#X connect 30 0 3 1;
+#X connect 30 0 4 1;
+#X connect 32 0 18 0;
+#X connect 32 1 23 0;
+#X connect 33 0 17 0;
+#X connect 33 1 24 0;
+#X connect 33 2 11 0;
+#X restore 167 221 pd fenvelope;
+#N canvas 867 125 1052 736 aenvelope 0;
+#X obj 113 33 inlet;
+#X obj 539 46 inlet;
+#X obj 216 137 * 123;
+#X obj 341 162 * 123;
+#X obj 468 202 route sustain;
+#X obj 471 317 -;
+#X obj 465 262 t b f;
+#X floatatom 465 235 5 0 0 0 - - -;
+#X obj 343 133 * 6;
+#X obj 341 190 + 50;
+#X obj 113 186 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 270 303 delay 100;
+#X obj 253 431 line~ 10 10;
+#X obj 146 369 pack 1 1;
+#X obj 271 381 pack 0 1;
+#X obj 257 645 clip~ -1 1;
+#X obj 312 580 dbtorms~;
+#X obj 254 682 outlet~;
+#X obj 469 289 f 1;
+#X obj 316 520 *~ 60;
+#X obj 316 547 +~ 40;
+#X obj 218 161 + 1;
+#X obj 142 341 f 1;
+#X obj 269 349 f 0;
+#X obj 309 271 + 3;
+#X text 318 681 amplitude;
+#X obj 316 461 *~ 1;
+#X obj 318 490 +~ 0;
+#X obj 319 348 f 125;
+#X obj 182 339 f 1;
+#X obj 296 608 lop~ 50;
+#X obj 484 511 r fromOF;
+#X obj 481 565 route smoothing;
+#X obj 483 538 route list;
+#X obj 224 49 inlet;
+#X obj 322 49 inlet;
+#X text 232 28 attack;
+#X text 330 28 decay;
+#X text 162 28 trigger;
+#X text 532 18 total time;
+#X obj 237 225 t f f;
+#X obj 102 243 t b b b;
+#X obj 280 325 t b b;
+#X connect 0 0 10 0;
+#X connect 1 0 2 1;
+#X connect 1 0 3 1;
+#X connect 2 0 21 0;
+#X connect 3 0 9 0;
+#X connect 4 0 7 0;
+#X connect 5 0 26 1;
+#X connect 6 0 18 0;
+#X connect 6 1 5 1;
+#X connect 7 0 6 0;
+#X connect 7 0 27 1;
+#X connect 8 0 3 0;
+#X connect 9 0 28 1;
+#X connect 10 0 41 0;
+#X connect 11 0 23 0;
+#X connect 11 0 42 0;
+#X connect 12 0 26 0;
+#X connect 13 0 12 0;
+#X connect 14 0 12 0;
+#X connect 15 0 17 0;
+#X connect 16 0 30 0;
+#X connect 18 0 5 0;
+#X connect 19 0 20 0;
+#X connect 20 0 16 0;
+#X connect 21 0 40 0;
+#X connect 22 0 13 0;
+#X connect 23 0 14 0;
+#X connect 24 0 11 1;
+#X connect 26 0 27 0;
+#X connect 27 0 19 0;
+#X connect 28 0 14 1;
+#X connect 29 0 13 1;
+#X connect 30 0 15 0;
+#X connect 31 0 33 0;
+#X connect 32 0 30 1;
+#X connect 33 0 32 0;
+#X connect 34 0 2 0;
+#X connect 35 0 8 0;
+#X connect 40 0 29 1;
+#X connect 40 1 24 0;
+#X connect 41 0 22 0;
+#X connect 41 1 29 0;
+#X connect 41 2 11 0;
+#X connect 42 0 23 0;
+#X connect 42 1 28 0;
+#X restore 259 222 pd aenvelope;
+#N canvas 22 194 893 724 reverb 0;
+#X obj 44 173 *~;
+#X obj 354 161 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X floatatom 344 184 5 0 0 0 - - -;
+#X obj 342 206 * -1;
+#X obj 343 232 + 1;
+#X obj 149 167 *~;
+#X floatatom 490 281 5 0 0 0 - - -;
+#X obj 96 206 rev1~ 70;
+#X obj 158 208 rev1~ 68;
+#X obj 538 113 vsl 15 128 0 100 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 490 307 + 3;
+#X obj 76 370 outlet~;
+#X obj 141 369 outlet~;
+#X obj 73 80 inlet~;
+#X obj 433 41 inlet;
+#X obj 507 53 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#N canvas 861 22 993 1015 interpolatorReverb 0;
+#X obj 71 34 inlet;
+#X text 66 12 slider control;
+#X floatatom 105 352 5 0 0 0 - - -;
+#X floatatom 181 356 5 0 0 0 - - -;
+#X floatatom 246 356 5 0 0 0 - - -;
+#X floatatom 316 352 5 0 0 0 - - -;
+#X obj 530 652 float 0.1;
+#X text 60 827 rev mix;
+#X obj 530 773 outlet;
+#X text 532 751 rev dec time;
+#X obj 116 408 / 32;
+#X obj 181 408 / 32;
+#X obj 243 410 / 32;
+#X obj 316 408 / 32;
+#X obj 177 381 - 32;
+#X obj 245 382 - 64;
+#X obj 317 378 - 96;
+#X text 544 477 calc frac;
+#X obj 70 500 -;
+#X obj 70 481 float 1;
+#X obj 814 575 loadbang;
+#X obj 603 650 float 0.15;
+#X obj 521 713 + 0;
+#X floatatom 126 524 5 0 0 0 - - -;
+#X floatatom 71 529 5 0 0 0 - - -;
+#X obj 505 685 * 0.1;
+#X obj 542 685 * 0.15;
+#X obj 613 709 + 0;
+#X obj 597 681 * 0.1;
+#X obj 634 681 * 0.15;
+#X obj 700 710 + 0;
+#X obj 793 711 + 0;
+#X obj 181 502 -;
+#X obj 178 483 float 1;
+#X floatatom 241 523 5 0 0 0 - - -;
+#X floatatom 182 524 5 0 0 0 - - -;
+#X obj 289 504 -;
+#X obj 289 485 float 1;
+#X floatatom 345 524 5 0 0 0 - - -;
+#X floatatom 290 526 5 0 0 0 - - -;
+#X text 772 621 insert values at points here;
+#X obj 396 504 -;
+#X obj 396 485 float 1;
+#X floatatom 503 518 5 0 0 0 - - -;
+#X floatatom 397 526 5 0 0 0 - - -;
+#X obj 684 682 * 30;
+#X obj 721 682 * 60;
+#X obj 774 682 * 60;
+#X obj 814 683 * 90;
+#X obj 114 825 outlet;
+#X obj 251 643 loadbang;
+#X obj 106 754 + 0;
+#X obj 87 710 * 0.1;
+#X obj 124 710 * 0.15;
+#X obj 195 734 + 0;
+#X obj 179 706 * 0.1;
+#X obj 216 706 * 0.15;
+#X obj 282 735 + 0;
+#X obj 375 736 + 0;
+#X text 25 651 insert values at points here;
+#X obj 266 707 * 30;
+#X obj 303 707 * 60;
+#X obj 356 707 * 60;
+#X obj 396 708 * 90;
+#X text 114 776 comment;
+#X obj 112 677 float 0;
+#X obj 253 677 float 0.3;
+#X obj 325 675 float 0.6;
+#X obj 393 674 float 1;
+#X obj 185 675 float 0.02;
+#X obj 671 652 float 20;
+#X obj 812 650 float 65;
+#X obj 743 650 float 40;
+#X obj 174 93 < 32;
+#X obj 159 119 &&;
+#X floatatom 168 141 5 0 0 0 - - -;
+#X obj 143 93 >= 0;
+#X obj 236 118 &&;
+#X obj 316 117 &&;
+#X obj 401 116 &&;
+#X obj 220 92 >= 32;
+#X obj 257 92 < 64;
+#X obj 296 92 >= 64;
+#X obj 337 91 < 96;
+#X obj 385 90 >= 96;
+#X obj 422 90 < 128;
+#X floatatom 230 140 5 0 0 0 - - -;
+#X floatatom 311 138 5 0 0 0 - - -;
+#X floatatom 395 137 5 0 0 0 - - -;
+#X obj 230 167 * 2;
+#X obj 312 166 * 3;
+#X obj 393 166 * 4;
+#X obj 203 224 +;
+#X obj 355 219 +;
+#X obj 272 265 +;
+#X obj 354 193 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 272 243 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 203 194 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 212 47 t f f f f f f f f;
+#X obj 103 57 t f f;
+#X obj 394 457 t b f f;
+#X obj 288 457 t b f f;
+#X obj 178 454 t b f f;
+#X obj 74 450 t b f f;
+#X obj 166 311 route 1 2 3 4;
+#X obj 166 288 pack f f;
+#X connect 0 0 99 0;
+#X connect 2 0 10 0;
+#X connect 3 0 14 0;
+#X connect 4 0 15 0;
+#X connect 5 0 16 0;
+#X connect 6 0 25 1;
+#X connect 10 0 103 0;
+#X connect 11 0 102 0;
+#X connect 12 0 101 0;
+#X connect 13 0 100 0;
+#X connect 14 0 11 0;
+#X connect 15 0 12 0;
+#X connect 16 0 13 0;
+#X connect 18 0 24 0;
+#X connect 19 0 18 0;
+#X connect 20 0 6 0;
+#X connect 20 0 21 0;
+#X connect 20 0 70 0;
+#X connect 20 0 71 0;
+#X connect 20 0 72 0;
+#X connect 21 0 26 1;
+#X connect 21 0 28 1;
+#X connect 22 0 8 0;
+#X connect 23 0 26 0;
+#X connect 23 0 53 0;
+#X connect 24 0 25 0;
+#X connect 24 0 52 0;
+#X connect 25 0 22 0;
+#X connect 26 0 22 1;
+#X connect 27 0 8 0;
+#X connect 28 0 27 0;
+#X connect 29 0 27 1;
+#X connect 30 0 8 0;
+#X connect 31 0 8 0;
+#X connect 32 0 35 0;
+#X connect 33 0 32 0;
+#X connect 34 0 29 0;
+#X connect 34 0 56 0;
+#X connect 35 0 28 0;
+#X connect 35 0 55 0;
+#X connect 36 0 39 0;
+#X connect 37 0 36 0;
+#X connect 38 0 46 0;
+#X connect 38 0 61 0;
+#X connect 39 0 45 0;
+#X connect 39 0 60 0;
+#X connect 41 0 44 0;
+#X connect 42 0 41 0;
+#X connect 43 0 48 0;
+#X connect 43 0 63 0;
+#X connect 44 0 47 0;
+#X connect 44 0 62 0;
+#X connect 45 0 30 0;
+#X connect 46 0 30 1;
+#X connect 47 0 31 0;
+#X connect 48 0 31 1;
+#X connect 50 0 65 0;
+#X connect 50 0 66 0;
+#X connect 50 0 67 0;
+#X connect 50 0 68 0;
+#X connect 50 0 69 0;
+#X connect 51 0 49 0;
+#X connect 52 0 51 0;
+#X connect 53 0 51 1;
+#X connect 54 0 49 0;
+#X connect 55 0 54 0;
+#X connect 56 0 54 1;
+#X connect 57 0 49 0;
+#X connect 58 0 49 0;
+#X connect 60 0 57 0;
+#X connect 61 0 57 1;
+#X connect 62 0 58 0;
+#X connect 63 0 58 1;
+#X connect 65 0 52 1;
+#X connect 66 0 56 1;
+#X connect 66 0 60 1;
+#X connect 67 0 61 1;
+#X connect 67 0 62 1;
+#X connect 68 0 63 1;
+#X connect 69 0 53 1;
+#X connect 69 0 55 1;
+#X connect 70 0 29 1;
+#X connect 70 0 45 1;
+#X connect 71 0 48 1;
+#X connect 72 0 46 1;
+#X connect 72 0 47 1;
+#X connect 73 0 74 1;
+#X connect 74 0 75 0;
+#X connect 75 0 92 0;
+#X connect 76 0 74 0;
+#X connect 77 0 86 0;
+#X connect 78 0 87 0;
+#X connect 79 0 88 0;
+#X connect 80 0 77 0;
+#X connect 81 0 77 1;
+#X connect 82 0 78 0;
+#X connect 83 0 78 1;
+#X connect 84 0 79 0;
+#X connect 85 0 79 1;
+#X connect 86 0 89 0;
+#X connect 87 0 90 0;
+#X connect 88 0 91 0;
+#X connect 89 0 92 1;
+#X connect 89 0 97 0;
+#X connect 90 0 93 0;
+#X connect 91 0 93 1;
+#X connect 91 0 95 0;
+#X connect 92 0 94 0;
+#X connect 93 0 94 1;
+#X connect 93 0 96 0;
+#X connect 94 0 105 0;
+#X connect 95 0 93 0;
+#X connect 96 0 94 0;
+#X connect 97 0 92 0;
+#X connect 98 0 76 0;
+#X connect 98 1 73 0;
+#X connect 98 2 80 0;
+#X connect 98 3 81 0;
+#X connect 98 4 82 0;
+#X connect 98 5 83 0;
+#X connect 98 6 84 0;
+#X connect 98 7 85 0;
+#X connect 99 0 98 0;
+#X connect 99 1 105 1;
+#X connect 100 0 42 0;
+#X connect 100 1 41 1;
+#X connect 100 2 43 0;
+#X connect 101 0 37 0;
+#X connect 101 1 36 1;
+#X connect 101 2 38 0;
+#X connect 102 0 33 0;
+#X connect 102 1 32 1;
+#X connect 102 2 34 0;
+#X connect 103 0 19 0;
+#X connect 103 1 18 1;
+#X connect 103 2 23 0;
+#X connect 104 0 2 0;
+#X connect 104 1 3 0;
+#X connect 104 2 4 0;
+#X connect 104 3 5 0;
+#X connect 105 0 104 0;
+#X restore 379 97 pd interpolatorReverb;
+#X connect 0 0 11 0;
+#X connect 0 0 12 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 2 0 5 1;
+#X connect 3 0 4 0;
+#X connect 4 0 0 1;
+#X connect 5 0 7 0;
+#X connect 5 0 8 0;
+#X connect 6 0 7 1;
+#X connect 6 0 10 0;
+#X connect 7 0 11 0;
+#X connect 8 0 12 0;
+#X connect 9 0 6 0;
+#X connect 10 0 8 1;
+#X connect 13 0 0 0;
+#X connect 13 0 5 0;
+#X connect 14 0 16 0;
+#X connect 15 0 16 0;
+#X connect 16 0 2 0;
+#X connect 16 1 6 0;
+#X restore 73 407 pd reverb;
+#X obj 664 -65 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 92 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 120 -86 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 80 56 / 127;
+#X obj 119 57 / 127;
+#X text 81 -112 attack;
+#X text 124 -112 decay;
+#X obj -42 -77 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text -53 -112 pitch;
+#X text -7 -114 duration;
+#X obj 314 -85 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 346 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X obj 301 53 / 127;
+#X text 299 -115 ftype;
+#X text 342 -115 ffreq;
+#X obj 380 -83 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 381 -116 reson;
+#X obj 569 -90 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 562 -111 reverb;
+#X obj 344 82 +;
+#X floatatom 339 135 5 0 0 0 - - -;
+#X obj 92 335 *~ 0.1;
+#X obj 46 -84 vsl 15 128 0 127 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 1;
+#X text 35 -102 wavef;
+#X text 655 -95 trigger;
+#X obj -38 -168 route pitch;
+#X obj 44 -169 route waveform;
+#X obj 138 -169 route attack;
+#X obj 221 -171 route decay;
+#X obj 301 -170 route fType;
+#X obj 378 -167 route fFreq;
+#X obj 459 -169 route reson;
+#X obj 547 -172 route reverb;
+#X obj 636 -172 route trigger;
+#X obj 337 110 - 185;
+#X obj -42 102 + 30;
+#X obj -41 72 / 3;
+#X obj 93 477 outlet~;
+#X obj 153 476 outlet~;
+#X obj 647 -232 inlet;
+#X text 181 -80 candidate synth;
+#X text 177 -51 candidate synth;
+#X text 176 -24 candidate synth;
+#X text 174 4 candidate synth;
+#X obj 134 -233 inlet;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 28 0;
+#X connect 3 0 6 0;
+#X connect 4 0 1 1;
+#X connect 5 0 2 1;
+#X connect 6 0 44 0;
+#X connect 6 1 45 0;
+#X connect 7 0 4 0;
+#X connect 7 0 5 0;
+#X connect 8 0 10 0;
+#X connect 9 0 11 0;
+#X connect 10 0 4 1;
+#X connect 10 0 5 1;
+#X connect 11 0 4 2;
+#X connect 11 0 5 2;
+#X connect 14 0 43 0;
+#X connect 17 0 19 0;
+#X connect 18 0 26 0;
+#X connect 19 0 1 2;
+#X connect 22 0 1 4;
+#X connect 24 0 6 1;
+#X connect 26 0 41 0;
+#X connect 28 0 3 0;
+#X connect 29 0 0 0;
+#X connect 32 0 14 0;
+#X connect 33 0 29 0;
+#X connect 34 0 8 0;
+#X connect 35 0 9 0;
+#X connect 36 0 17 0;
+#X connect 37 0 18 0;
+#X connect 38 0 22 0;
+#X connect 39 0 24 0;
+#X connect 40 0 7 0;
+#X connect 41 0 1 3;
+#X connect 41 0 27 0;
+#X connect 42 0 26 1;
+#X connect 42 0 0 1;
+#X connect 43 0 42 0;
+#X connect 46 0 7 0;
+#X connect 51 0 32 0;
+#X connect 51 0 33 0;
+#X connect 51 0 34 0;
+#X connect 51 0 35 0;
+#X connect 51 0 36 0;
+#X connect 51 0 37 0;
+#X connect 51 0 38 0;
+#X connect 51 0 39 0;
+#X connect 51 0 40 0;
+#X restore 41 -45 pd candidateSynth;
+#X obj 100 162 +~;
+#X obj 133 163 +~;
+#X obj -14 -179 int 1;
+#X obj 28 -180 int 2;
+#X obj 23 -136 gate 2;
+#X obj 136 -68 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 313 -71 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj -14 -200 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 277 -128 route toTarget;
+#X obj 224 -191 r fromOF;
+#X obj 153 -128 route toCandidate;
+#X obj 43 -289 route startTrigger;
+#X text 180 159 to do swap between with short fade to prevent reverb
+mixing up;
+#X text 278 110 to do: remove sine osc or make it FM and do something
+clever;
+#X obj 141 -93 route trigger;
+#X obj 288 -99 route trigger;
+#X connect 1 0 9 1;
+#X connect 2 0 1 0;
+#X connect 2 0 12 0;
+#X connect 3 0 5 1;
+#X connect 3 1 6 1;
+#X connect 4 0 5 0;
+#X connect 4 1 6 0;
+#X connect 5 0 0 0;
+#X connect 6 0 0 1;
+#X connect 7 0 9 0;
+#X connect 8 0 9 0;
+#X connect 9 0 8 0;
+#X connect 9 0 10 0;
+#X connect 9 1 7 0;
+#X connect 9 1 11 0;
+#X connect 10 0 4 1;
+#X connect 11 0 3 1;
+#X connect 12 0 7 0;
+#X connect 13 0 3 0;
+#X connect 13 0 20 0;
+#X connect 14 0 13 0;
+#X connect 14 0 15 0;
+#X connect 15 0 4 0;
+#X connect 15 0 19 0;
+#X connect 16 0 2 0;
+#X connect 19 0 10 0;
+#X connect 20 0 11 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testApp.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,168 @@
+#pragma once
+
+#include "ofMain.h"
+
+//#include "ofxiPhone.h"
+//#include "ofxiPhoneExtras.h"
+// #include "ofxiPhoneExternalDisplay.h"
+
+#include "ofxiOS.h"
+#include "ofxiOSExtras.h"
+
+#include "ofxOsc.h"
+#include "ofxMidi.h"
+#include "2dvector.h"
+#include "AppCore.h"
+#include "eventLogger.h"
+#include "ofxPd.h"
+#include "json.h"
+#import "QuestionnaireViewController.h"
+#import "HelpViewController.h"
+#import "UsernameAlertViewController.h"
+#import "IntroViewController.h"
+#include "sliderPanel.h"
+#include "UIElement.h"
+#include "UIElementContainer.h"
+#include "buttron.h"
+#include "ButtronSlider.h"
+#include "buttronXY.h"
+#include "UIGrid.h"
+#include "MessageOrganiser.h"
+#include "TestController.h"
+#include "timeController.h"
+#include <buttonPanel.h>
+#include "targetSymbol.h"
+#include "3Dbox.h"
+#include "TextPanel.h"
+//#define OSC_HOST "169.254.1.1"
+//#define OSC_PORT 12345
+
+#define SLIDER_GUI_WIDTH 256
+#define SLIDER_HEIGHT 256
+#define NUM_PARAMS 10
+
+
+
+class testApp : public ofxiOSApp , public ofxMidiListener, public ofxMidiConnectionListener {
+
+	
+public:
+    ofTrueTypeFont verdBig;
+    bool sendMIDIAndOSC;
+    bool paused;
+    
+    int midiChannel;
+    int midiOffset;
+    double tx,ty;
+    ofColor generalBackground;
+    //
+    void initialiseGUIs();
+    void initialiseVariables();
+    void initialiseMIDI();
+    void setupUIElements();
+    
+    void setup();
+    void update();
+    void draw();
+    void drawUIElements();
+    void exit();
+
+    HelpViewController *helpViewController;
+    QuestionnaireViewController *questionnaireViewController;
+    UsernameAlertViewController *usernameAlertViewController;
+    IntroViewController * introViewController;
+    
+    MessageOrganiser messageOrganiser;
+    TestController* testController;
+    //TimeController timeController;
+    interfaceType whichInterfaceShowing, previousInterface;
+    
+    // pannels buttrons and slidertrons
+    vector<UIElement *> UIElements;
+    
+    void touchToUIElements(int x, int y, touchType ttype, int tid);
+    void touchDown(ofTouchEventArgs &touch);
+    void touchMoved(ofTouchEventArgs &touch);
+    void touchUp(ofTouchEventArgs &touch);
+    void touchDoubleTap(ofTouchEventArgs &touch);
+    void touchCancelled(ofTouchEventArgs &touch);
+    double ofFixGetWidth();
+    double ofFixGetHeight();
+    ofTouchEventArgs transformTouchCoords(ofTouchEventArgs &point);
+    ofLight light;
+        
+    void lostFocus();
+    void gotFocus();
+    void gotMemoryWarning();
+    void deviceOrientationChanged(int newOrientation);
+
+//    ofxOscSender sender;
+//    void sendOSCParams();
+
+    void showQuestionnaire();
+    void questionnaireHidden(vector<int> answers,  const char* userComments);
+
+    void showIntro();
+    void introHidden();
+    void startTheTests();
+    void showHelp();
+    void helpHidden();
+    void setupNewUser();
+    void appModeChange(interfaceType mode);
+
+    void sendParametersToPD();
+    
+    void sendMidiParams();
+    void sendMidiParam(int which);
+    
+    // audio callbacks
+    float *  wavetableNew;
+    int bufSize;
+    void drawWaveform();
+    void drawScore();
+	void audioReceived(float * input, int bufferSize, int nChannels);
+	void audioRequested(float * output, int bufferSize, int nChannels);
+    
+    AppCore core;
+    
+    // message
+    void addMessage(string msg);
+	
+	// midi message callback
+	void newMidiMessage(ofxMidiMessage& msg);
+	
+	// midi device (dis)connection event callbacks
+	void midiInputAdded(string name, bool isNetwork);
+	void midiInputRemoved(string name, bool isNetwork);
+	
+	void midiOutputAdded(string nam, bool isNetwork);
+	void midiOutputRemoved(string name, bool isNetwork);
+    
+	vector<ofxMidiIn*> inputs;
+	vector<ofxMidiOut*> outputs;
+    
+	deque<string> messages;
+	int maxMessages;
+	
+	int note, ctl;
+	vector<unsigned char> bytes;
+    
+    // in the h file:
+    ofTrueTypeFont myfont;
+
+    void windowResized(int w, int h){};
+    
+    void rotateToPortrait(){};
+    void rotateToPortraitUpSideDown(){};
+    void rotateToLandscapeLeft(){};
+    void rotateToLandscapeRight(){};
+    void toggleAutoRotation(){};
+    
+};
+
+// should be off split into
+// GUI controller
+// parameter converter
+// MIDI stuff(?)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testApp.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,734 @@
+#include "testApp.h"
+#include "ofAppiOSWindow.h"
+
+extern EventLogger eventLogger;
+
+// static members inited here. not my choice.
+int SynthParam::mappingUID = 88000;
+//--------------------------------------------------------------
+void testApp::setup(){
+    
+    
+    
+    ofxiPhoneSetOrientation( OF_ORIENTATION_90_LEFT );
+    //ofxiPhoneExternalDisplay::mirrorOn();
+    [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
+    // initilaise
+    
+    
+    initialiseVariables();
+    
+    
+    testController = new TestController;
+    
+    messageOrganiser.init(&core, testController);
+    timeController.init();
+    initialiseGUIs();
+    initialiseMIDI();
+    setupUIElements();
+
+
+    
+    light.setSpotlight(45. , 1.);
+    light.enable();
+    ofEnableSeparateSpecularLight();
+    ofEnableDepthTest();
+    ofEnableAlphaBlending();
+    // in setup:
+    myfont.loadFont("NewMedia Fett.ttf", 32);
+    
+    verdBig.loadFont("verdana.ttf", 18, true, true);
+	verdBig.setLineHeight(18.0f);
+	verdBig.setLetterSpacing(1.037);
+
+    //--------------------------------------
+    
+    eventLogger.startLoadAll();
+    //--------------------------------------
+    
+    // now do things that will affect the start up state of the app
+    
+    // initialise PD
+    
+	int ticksPerBuffer = 8;	// 8 * 64 = buffer len of 512
+	core.setup(2, 2, 44100, ticksPerBuffer);
+
+    // setup OF sound stream
+    bufSize = ofxPd::blockSize()*ticksPerBuffer;
+    wavetableNew = (float *) malloc(bufSize * sizeof(float));
+    
+	ofSoundStreamSetup(2, 2, this, 44100, ofxPd::blockSize()*ticksPerBuffer, 3);
+    
+    if(true){ // force start
+        startTheTests();
+    }else{
+        
+        if(eventLogger.questionnaireCompleted){ // then show play again dialog, and log the test number
+            
+        }else{
+            // then we're in timed session mode
+            showIntro();
+        }
+    }
+    paused = false;
+    
+    
+    eventLogger.logEvent(APP_LOADED);
+
+    ofSoundStreamStart();
+
+}
+
+//-----------------------------------------------------------------------------
+
+//DeviceID3523537000
+void testApp::initialiseVariables(){
+    paused = true;
+    ofBackground( 0, 0, 0 );
+    //ofEnableAlphaBlending();
+    //ofEnableSmoothing();
+    
+	// open an outgoing connection to HOST:PORT for OSC
+	// sender.setup( OSC_HOST, OSC_PORT );
+    ofSetFrameRate(60);
+    
+
+}
+//---------------------------------------------------------
+void testApp::initialiseGUIs(){
+
+    // set up iOS gui stuff
+    
+    helpViewController	= [[HelpViewController alloc] initWithNibName:@"HelpViewController" bundle:nil];
+    [ofxiPhoneGetGLParentView() addSubview:helpViewController.view];
+    [helpViewController setAppRef:(__bridge id)this];
+    helpViewController.view.hidden = YES;
+    
+
+    usernameAlertViewController = [[UsernameAlertViewController alloc] init];
+    [usernameAlertViewController setAppRef:(__bridge id)this];
+ 
+}
+
+//--------------------------------------------------------------
+void testApp::setupUIElements(){
+
+    // eventually: sliderpanel, topbuttonpanel, submitbuttonpanel, countdown panel,
+    
+    // --------------------- BUTTONS
+    UIProps p;
+    ofBackground(p.generalBackground);
+
+    ButtonPanel* bottomButtonPanel = new ButtonPanel(1,160+p.sliderPanelHeight,ofGetWidth(),250,p);
+
+    Buttron* playTargetButton = new Buttron(p.buttonWidth*0.2,680, p);
+    playTargetButton->setLabel("Target");
+    messageOrganiser.mapButtonToAction(playTargetButton, TRIGGER_TARGET_ID);
+    bottomButtonPanel->addButton(playTargetButton);
+    messageOrganiser.setTargetButton(playTargetButton);
+
+    Buttron * playCandidateButton = new Buttron(p.buttonWidth*1.4,680, p);
+    playCandidateButton->setLabel("Current");
+    messageOrganiser.mapButtonToAction(playCandidateButton, TRIGGER_CANDIDATE_ID);
+    bottomButtonPanel->addButton(playCandidateButton);
+    
+    
+    // submit button - only one for now
+    Buttron * submitButton = new Buttron(ofGetWidth()*0.5 - p.buttonWidth*0.5,680, p);
+    submitButton->setLabel("Submit");
+    messageOrganiser.mapButtonToAction(submitButton, SUBMIT_CANDIDATE);
+    bottomButtonPanel->addButton(submitButton);
+    
+    //  button - just for spacing pruposes
+    Buttron * spacerButton = new Buttron(ofGetWidth()*0.5 - p.buttonWidth*0.5,680, p);
+    spacerButton->setLabel("-");
+    messageOrganiser.mapButtonToAction(spacerButton, TRIGGER_CANDIDATE_ID);
+    bottomButtonPanel->addButton(spacerButton);
+    spacerButton->hide();
+    
+    Buttron * spacerButton2 = new Buttron(ofGetWidth()*0.5 - p.buttonWidth*0.5,680, p);
+    spacerButton2->setLabel("-");
+    messageOrganiser.mapButtonToAction(spacerButton2, TRIGGER_CANDIDATE_ID);
+    bottomButtonPanel->addButton(spacerButton2);
+    spacerButton2->hide();
+    
+    messageOrganiser.setBottomPanel(bottomButtonPanel);
+    UIElements.push_back(bottomButtonPanel);
+    bottomButtonPanel->showBorder(false);
+
+
+
+    // ------------------------------------ SLIDERS
+
+    vector<controllerType> sl2;
+    sl2.push_back(SLIDER);
+    
+    SliderPanel * controlPanel = new SliderPanel(1,
+                                                 160,
+                                                 ofGetWidth(),
+                                                 p.sliderPanelHeight,
+                                                 p,
+                                                 sl2);
+    
+    UIElements.push_back(controlPanel);
+    messageOrganiser.setControlPanel(controlPanel);
+    controlPanel->showBorder(true);
+    
+    // -   -   - - - -- -  - OTHER BITS
+    
+    CountdownText * countDownBox = new CountdownText("5" , 500, 380, 455, 455, p);
+    UIElements.push_back(countDownBox);
+    messageOrganiser.setCountdownPanel(countDownBox);
+    countDownBox->hide();
+    
+    TextPanel * scoreFeedback = new TextPanel("Feedback panel", ofGetWidth()*0.5 - p.buttonWidth*0.5, 666, 400,100,p);
+    scoreFeedback->setFontSize(SMALLFONT);
+    UIElements.push_back(scoreFeedback);
+    messageOrganiser.setScorePanel(scoreFeedback);
+    scoreFeedback->hide();
+    
+    TextPanel * finishPanel = new TextPanel("Finish txt panel", 250, 250, 1000,400,p);
+    finishPanel->setFontSize(LARGEFONT);
+    finishPanel->setText("Experiment completed");
+    messageOrganiser.setFinishPanel(finishPanel);
+    
+    UIElements.push_back(finishPanel);
+    finishPanel->hide();
+
+    
+    Buttron * newTestButton = new Buttron(ofGetWidth()-300,690, p);
+    newTestButton->setLabel("Next Test");
+    UIElements.push_back(newTestButton);
+    messageOrganiser.mapButtonToAction(newTestButton, NEW_TEST_ID);
+    newTestButton->hide();
+    messageOrganiser.setNewTestButton(newTestButton);
+    
+    TargetSymbol* targetSymbol = new TargetSymbol(ofGetWidth()*0.5,160,30,p);
+    messageOrganiser.setTargetSymbol(targetSymbol);
+    UIElements.push_back(targetSymbol);
+    
+    // alternation speed
+
+    
+//    ButtronSlider * speedSlider = new ButtronSlider(ofGetWidth()-60, 210, 50, p.sliderHeight/2,FILL, p);
+//    UIElements.push_back(speedSlider);
+//    messageOrganiser.mapButtonToAction(speedSlider, SPEED_CHANGE_ID);
+//    
+//    Buttron * altButton = new Buttron(ofGetWidth()-60, 500, 50, 50,p);
+//    UIElements.push_back(altButton);
+//    altButton->setLabel("Alt");
+//    messageOrganiser.mapButtonToAction(altButton, START_ALTERNATE_ID);
+    
+//    TextPanel * speedLabel = new TextPanel("Speed", ofGetWidth()-55, 195, 50,20,p);
+//    speedLabel->setText("Speed");
+//    speedLabel->setFontSize(SMALLFONT);
+//    speedLabel->show();
+//    UIElements.push_back(speedLabel);
+    
+    // volume
+//    ButtronSlider * volumeSlider = new ButtronSlider(50, 210, 30, p.sliderHeight,FILL, p);
+//    UIElements.push_back(volumeSlider);
+//    messageOrganiser.mapButtonToAction(volumeSlider, VOLUME_CHANGE_ID);
+}
+//--------------------------------------------------------------------------
+void testApp::initialiseMIDI(){
+    
+    /////////////////////////
+    // MIDI
+    
+    midiChannel = 8;
+    midiOffset = 0;
+	
+	// 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
+
+}
+//--------------------------------------------------------------
+
+template <class T>
+void deleteVectorOfPointers( T * inVectorOfPointers )
+{
+    typename T::iterator i;
+    for ( i = inVectorOfPointers->begin() ; i < inVectorOfPointers->end(); i++ )
+    {
+        delete * i;
+    }
+    //delete inVectorOfPointers;
+}
+
+
+//--------------------------------------------------------------
+void testApp::exit(){
+    eventLogger.logEvent(APP_EXITED);
+    eventLogger.exitAndSave();
+    
+    core.exit();
+    
+    // are these handled automatically?
+    //[introViewController release];
+    //[topButtonViewController release];
+    //[bottomTabViewController release];
+    
+    // clean up MIDI
+	for(int i = 0; i < inputs.size(); ++i) {
+		inputs[i]->closePort();
+		inputs[i]->removeListener(this);
+		delete inputs[i];
+	}
+    
+	for(int i = 0; i < outputs.size(); ++i) {
+		outputs[i]->closePort();
+		delete outputs[i];
+	}
+    deleteVectorOfPointers(&UIElements); // TODO this crashes??
+    
+    
+    delete testController;
+    
+    cout << "exit done \n";
+}
+
+#pragma mark GUI
+////////////////////////////
+// These functions called from iOS toolbars
+//--------------------------------------------------------------
+
+//--------------------------------------------------------------
+void testApp::showQuestionnaire(){
+
+    
+    questionnaireViewController	= [[QuestionnaireViewController alloc] initWithNibName:@"QuestionnaireViewController" bundle:nil];
+    [ofxiPhoneGetGLParentView() addSubview:questionnaireViewController.view];
+	
+    [questionnaireViewController setAppRef:(__bridge id)this];
+    [questionnaireViewController show:(__bridge id)this];
+    
+    whichInterfaceShowing = QUESTIONNAIRE;
+    
+    
+}
+//--------------------------------------------------------------
+void testApp::questionnaireHidden(vector<int> answers, const char* userComments){
+    // send answers to server as json
+    eventLogger.questionnaireAnswersObtained(answers, userComments);
+
+}
+
+//--------------------------------------------------------------
+void testApp::showIntro(){
+    
+    cout << "SHOW INTRO\n";
+
+    introViewController	= [[IntroViewController alloc] initWithNibName:@"IntroViewController" bundle:nil];
+    [ofxiPhoneGetGLParentView() addSubview:introViewController.view];
+	
+    [introViewController setAppRef:(__bridge id)this];
+    [introViewController show:(__bridge id)this];
+    
+    whichInterfaceShowing = INTRO;
+    
+}
+//--------------------------------------------------------------
+void testApp::introHidden(){
+    eventLogger.consentGiven = true;
+    eventLogger.logEvent(INTRO_CONSENTED);
+    [usernameAlertViewController showUserNamePrompt];
+    // after prompt goes it calls startTheTests()
+}
+
+//--------------------------------------------------------------
+void testApp::startTheTests(){
+    eventLogger.logEvent(START_THE_TESTS);
+    whichInterfaceShowing = COUNT_DOWN;
+    // do countdown etc
+    messageOrganiser.countdownToNewTest();
+    // TODO how is testApp going to kknow whichInterfaceShowing ???
+    
+}
+//--------------------------------------------------------------
+//--------------------------------------------------------------
+void testApp::showHelp(){
+    // stop clock etc
+    previousInterface = whichInterfaceShowing;
+    whichInterfaceShowing = HELP;
+    helpViewController.view.hidden = NO;
+    eventLogger.logEvent(HELP_PRESSED);
+    
+}
+void testApp::helpHidden(){
+    whichInterfaceShowing = previousInterface;
+    
+}
+//--------------------------------------------------------------
+//--------------------------------------------------------------
+//--------------------------------------------------------------
+#pragma mark sending to pd and midi
+void testApp::sendParametersToPD(){
+
+    
+}
+//--------------------------------------------------------------
+void testApp::sendMidiParam(int which){
+    int midiChannel = 8;
+    int offset = 0;
+    
+    for(int i = 0; i < outputs.size(); ++i) {
+        outputs[i]->sendControlChange(midiChannel, offset+which, 66);
+    }
+    
+    
+}
+
+//--------------------------------------------------------------
+//void testApp::sendOSCParams(){
+//       
+//    ofxOscMessage m;
+//    m.setAddress( "Template" );
+//
+//    m.addFloatArg(9.9999);
+//
+//    sender.sendMessage( m );
+//}
+//--------------------------------------------------------------
+
+void testApp::setupNewUser(){
+    // this function is for supervised trials with my ipad
+    eventLogger.newUser();
+}
+//--------------------------------------------------------------
+#pragma mark STANDARD OF FUNCTIONS
+//--------------------------------------------------------------
+void testApp::update(){
+    
+    if(paused) return;
+    
+    // run timer check here
+    // look at time, work out difference
+    timeController.tick();
+    
+    // test mutex crash thing
+    //eventLogger.logEvent(CANDIDATE_PLAYED);
+}
+//--------------------------------------------------------------
+
+void testApp::appModeChange(interfaceType mode){
+    whichInterfaceShowing = mode;
+}
+
+
+//------------------------------------------------------------------------
+
+void testApp::draw(){
+    
+    switch (whichInterfaceShowing){
+        case QUESTIONNAIRE:
+            break;
+        case INTRO:
+            break;
+        case TEST_IN_PROGRESS:
+            break;
+        case SCORE_AND_HINT:
+            break;
+        case COUNT_DOWN:
+            break;
+        case READY_FOR_NEXT:
+            break;
+        default:
+            break;
+    }
+    
+    
+    
+    drawUIElements();
+    
+    //ofSetColor(234, 234, 234);
+    //ofLine(0,150,1024,150);
+    
+    //drawWaveform();
+    drawScore();
+    
+    
+
+}
+//------------------------------------------------------------------------
+void testApp::drawUIElements(){
+
+    vector<UIElement *>::iterator UIitr;
+    for(UIitr = UIElements.begin(); UIitr < UIElements.end(); UIitr++){
+        (*UIitr)->draw();
+    }
+}
+//------------------------------------------------------------------------
+void testApp::drawScore(){
+    ofColor txtCol = ofColor(150,235,200,255);
+    
+    int score = messageOrganiser.getScore();
+    stringstream msg;
+    
+    msg << "Test: " << testController->getCurrentTestLetter();
+    ofSetColor(txtCol);
+    verdBig.drawString(msg.str(), 40, 140);
+    msg.str(std::string());
+    
+    msg << "Score: " << score;
+    verdBig.drawString(msg.str(), 240, 140);
+    msg.str(std::string());
+    
+    pair<int,int> time;
+    time = messageOrganiser.getTime();
+    msg << "Time taken: " << time.first << ":" << time.second << endl;
+    verdBig.drawString(msg.str(), 600, 140);
+    
+}
+//------------------------------------------------------------------------
+
+//--------------------------------------------------------------
+// passes touch to UI elements
+//--------------------------------------------------------------
+
+void testApp::touchToUIElements(int x, int y, touchType ttype, int tid){
+    vector<UIElement *>::iterator UIitr;
+    for(UIitr = UIElements.begin(); UIitr < UIElements.end(); UIitr++){
+        (*UIitr)->touch(x,y,ttype, tid);
+    }
+}
+
+//--------------------------------------------------------------
+void testApp::touchDown(ofTouchEventArgs &touch){
+    //touch = transformTouchCoords(touch);
+    touchToUIElements(touch.x, touch.y, TOUCH_DOWN, touch.id);
+    
+}
+
+//--------------------------------------------------------------
+void testApp::touchMoved(ofTouchEventArgs &touch){
+
+    touchToUIElements(touch.x, touch.y, TOUCH_MOVED, touch.id);
+    
+}
+
+//--------------------------------------------------------------
+void testApp::touchUp(ofTouchEventArgs &touch){
+
+    touchToUIElements(touch.x, touch.y, TOUCH_UP, touch.id);
+}
+
+
+//--------------------------------------------------------------
+void testApp::touchDoubleTap(ofTouchEventArgs &touch){
+    
+}
+
+//--------------------------------------------------------------
+void testApp::lostFocus(){
+    //exit();
+}
+
+//--------------------------------------------------------------
+void testApp::gotFocus(){
+    
+}
+
+//--------------------------------------------------------------
+void testApp::gotMemoryWarning(){
+    
+}
+
+//--------------------------------------------------------------
+
+void testApp::deviceOrientationChanged(int newOrientation){
+    
+    cout << "orientation: " << newOrientation;
+    
+    // do something here?
+
+}
+
+
+
+//--------------------------------------------------------------
+void testApp::touchCancelled(ofTouchEventArgs& args){
+    
+}
+//---------------------------------------------------------------
+// AUDIO STUFF
+//---------------------------------------------------------------
+
+#pragma mark AUDIO STREAMS
+//--------------------------------------------------------------
+void testApp::audioReceived(float * input, int bufferSize, int nChannels) {
+	//core.audioReceived(input, bufferSize, nChannels);
+}
+
+void testApp::audioRequested(float * output, int bufferSize, int nChannels) {
+
+	core.audioRequested(output, bufferSize, nChannels);
+//    for(int i=0;i<bufferSize/2;i++){
+//        output[i] = 0.2;
+//    }
+//    // pass buffer to drawable thing
+//    for(int i=0;i<bufferSize;i++){
+//        wavetableNew[i] = output[i];
+//    }
+    
+}
+
+void testApp::drawWaveform(){
+    // draw the actual waveform in the corner
+    
+    int width = 768;
+    int height = 128;
+    double sampval = 0.0;
+    int leftsampnum = 0;
+    int rightsampnum = 0;
+    float sampscale = 0.0, prevsampscale = 0.0, interp = 0.0;
+    
+    ofSetColor(256, 0, 0);
+    double step = double(bufSize)/width; // how much we are stepping thru wave per pixel
+    for(int i = 0; i < width; i++){
+        
+        leftsampnum = floor(i * step); // basic nearest neighbour interpolation
+        rightsampnum = ceil(i*step);
+        interp  = (i*step)-leftsampnum;
+        if(rightsampnum < bufSize){
+            sampval = (1 - interp)*wavetableNew[leftsampnum] + interp*wavetableNew[rightsampnum];
+        }
+        sampscale = (sampval * 700) + height/2.0; // centre and scale
+        ofSetLineWidth(2);
+        ofLine(sampscale, i, prevsampscale, i-1); // draw a line from pixel to pixel (?)
+        prevsampscale = sampscale;
+    }
+    
+}
+//---------------------------------------------------------------
+#pragma mark UTILITIES
+//-------------------------------------------------------------------------
+//--------------------------------------------------------------
+
+#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) {
+    
+    // looks out for: 30 31 32 on channel 8
+    if(msg.channel == midiChannel && msg.status == MIDI_CONTROL_CHANGE){
+        int ctl_num = msg.control - 30;
+        int ctl_val = msg.value;
+        // TODO route control change message here
+        //cout << " ctrl : " << ctl_num << " : " << ctl_val << endl;
+        messageOrganiser.midiFromLeap(ctl_num, ctl_val);
+    }
+ 
+}
+
+//--------------------------------------------------------------
+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;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timeController.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,80 @@
+    //
+//  timeController.h
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/02/2014.
+//
+//
+
+#ifndef __tweakathlon__timeController__
+#define __tweakathlon__timeController__
+#include "ofMain.h"
+#include <iostream>
+#include "boost/function.hpp"
+#include <boost/bind.hpp>
+#import "TimedCallController.h"
+
+typedef boost::function<void(void)> TimerCallbackFunction;
+typedef map<unsigned long long, TimerCallbackFunction> TimesAndCallsMap;
+typedef std::pair<unsigned long long, TimerCallbackFunction> TimeAndCallPair;
+
+typedef unsigned long long TimerID; // the id is just the time it's set to fire, microsecs(?)
+typedef unsigned long long TimerMicrosec; //microsecs(?)
+typedef unsigned long long TimerMillisec;
+
+class TimeController{
+    
+public:
+    
+
+    //----------------
+    //----------------
+    void init(){
+        iosTimer = [[TimedCallController alloc] init];
+        [iosTimer setAppRef:(id)this];
+    };
+
+    //----------------
+    // called from testApp.update()
+    void tick(){
+        TimerID timeNow = getMicrosecTimeNow();
+        callAndEraseAllExpired(timeNow);
+
+    };
+
+    //----------------
+    void cancelEvent(TimerID which);
+    //----------------
+    TimerID scheduleEvent(TimerCallbackFunction cbfunc, int howLongMillisec);
+    //----------------
+    void startStopwatch();
+    TimerMicrosec stopStopwatch();
+    TimerMicrosec getStopwatchElapsedTime();
+    
+    void startCountDown(){
+        
+    };
+    void countdownFinished(){
+        
+    };
+    //----------------
+
+private:
+    TimesAndCallsMap timesAndCalls;
+    TimerMillisec stopWatchStartTime; // millisec
+    bool stopWatchRunning;
+    //----------------
+    void callAndEraseAllExpired(TimerMicrosec timeNow);
+
+    TimedCallController* iosTimer;
+    
+    TimerMicrosec getMicrosecTimeNow(){
+        double time_sec = [NSDate timeIntervalSinceReferenceDate];
+        return TimerMicrosec(time_sec*1000000);
+    }
+    
+};
+
+
+
+#endif /* defined(__tweakathlon__timeController__) */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timeController.mm	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,72 @@
+//
+//  timeController.cpp
+//  tweakathlon
+//
+//  Created by Robert Tubb on 10/02/2014.
+//
+//
+
+#include "timeController.h"
+
+TimeController timeController;
+
+
+//----------------
+void TimeController::callAndEraseAllExpired(TimerMicrosec timeNow){
+    
+    for(auto iter = timesAndCalls.begin(); iter != timesAndCalls.end(); ) {
+        if ( (*iter).first < timeNow) {
+            (*iter).second();
+            timesAndCalls.erase(iter++);
+        } else {
+            ++iter;
+        }
+    }
+};
+
+//----------------
+void TimeController::cancelEvent(TimerID which){
+    //
+    for(auto it = timesAndCalls.begin(); it != timesAndCalls.end();){
+        if ((*it).first == which) {
+            timesAndCalls.erase(it++);
+        } else {
+            ++it;
+        }
+    }
+    
+};
+//----------------
+TimerID TimeController::scheduleEvent(TimerCallbackFunction cbfunc, int howLongMillisec){
+    
+    TimerID fireTime = TimerID(getMicrosecTimeNow()+ 1000.0*howLongMillisec);
+    timesAndCalls.insert( TimeAndCallPair(fireTime, cbfunc));
+    
+    
+    return fireTime;
+};
+
+//----------------
+void TimeController::startStopwatch(){
+    if (stopWatchRunning){
+        cout << "ERROR stop watch already running" << endl;
+    }
+    
+    stopWatchStartTime = TimerMillisec(getMicrosecTimeNow()/1000);
+    stopWatchRunning = true;
+}
+//----------------
+TimerMillisec TimeController::stopStopwatch(){
+    if (!stopWatchRunning) return 0;
+    stopWatchRunning = false;
+    TimerMillisec elapsedTime = getMicrosecTimeNow()/1000 - stopWatchStartTime;
+    stopWatchStartTime = 0;
+    return elapsedTime;
+}
+//----------------
+TimerMillisec TimeController::getStopwatchElapsedTime(){
+    if (!stopWatchRunning) return 0;
+    TimerMillisec elapsedTime = getMicrosecTimeNow()/1000  - stopWatchStartTime;
+    return elapsedTime;
+}
+//----------------
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xyView.cpp	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,39 @@
+//
+//  xyView.cpp
+//  soundspeed
+//
+//  Created by Robert Tubb on 20/05/2013.
+//
+//
+
+#include "xyView.h"
+
+void XYView::draw(){
+    
+    ofFill();
+    ofNoFill();
+    ofSetColor(0,0,155);
+    
+    ofRect(screenX, screenY, width, height);
+    ofCircle(screenX+ctrlX, screenY+ctrlY, 60);
+    // cross hairs
+
+    ofLine(screenX+ctrlX - 30, screenY+ctrlY, screenX+ctrlX + 30, screenY+ctrlY);
+    ofLine(screenX+ctrlX,screenY+ctrlY - 30,screenX+ctrlX,screenY+ctrlY+30);
+    
+}
+
+bool XYView::handleTouch(double x, double y){
+    if(isInMyArea(x,y)){
+        ctrlX = x;
+        ctrlY = y;
+    
+        return true;
+    }else{
+        return false;
+    }
+    
+}
+bool XYView::isInMyArea(int x, int y){
+    return (x > screenX && x < screenX + width && y > screenY && y < screenY + height);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xyView.h	Fri Oct 10 11:46:42 2014 +0100
@@ -0,0 +1,39 @@
+//
+//  xyView.h
+//  soundspeed
+//
+//  Created by Robert Tubb on 20/05/2013.
+//
+//
+
+#ifndef __soundspeed__xyView__
+#define __soundspeed__xyView__
+
+#include <iostream>
+#include "ofMain.h"
+
+// very sketchy XY
+
+class XYView{
+private:
+    float screenX, screenY, height, width;
+    float ctrlX, ctrlY;
+    
+    bool isInMyArea(int x, int y);
+    
+public:
+    
+    XYView(double x, double y, double w, double h){
+        screenX = x;
+        screenY = y;
+        width = w;
+        height = h;
+        ctrlX = w*0.5;
+        ctrlY = h*0.5;
+    }
+    void draw();
+    bool handleTouch(double x, double y); // return false if ouside my area
+    
+};
+
+#endif /* defined(__soundspeed__xyView__) */