Mercurial > hg > tweakathon2ios
diff testApp.mm @ 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 | 851833072cf1 |
line wrap: on
line diff
--- /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; + } + } +}