rt300@0
|
1 //
|
rt300@0
|
2 // MessageOrganiser.h
|
rt300@0
|
3 // tweakathlon
|
rt300@0
|
4 //
|
rt300@0
|
5 // Created by Robert Tubb on 10/12/2013.
|
rt300@0
|
6 //
|
rt300@0
|
7 // This object handles the mapping from GUI to params
|
rt300@0
|
8 //
|
rt300@0
|
9 // and sends their messages to PD and eventLogger
|
rt300@0
|
10 #pragma once
|
rt300@0
|
11 #include "eventLogger.h"
|
rt300@0
|
12 #include <map.h>
|
rt300@0
|
13 #include <vector>
|
rt300@0
|
14 #include <string>
|
rt300@0
|
15 #include "boost/bind.hpp"
|
rt300@0
|
16 #include "boost/function.hpp"
|
rt300@0
|
17
|
rt300@0
|
18 #include <UIElement.h>
|
rt300@0
|
19 #include <Buttron.h>
|
rt300@0
|
20 #include <ButtronSlider.h>
|
rt300@0
|
21 #include <ButtronXY.h>
|
rt300@0
|
22 #include "AppCore.h"
|
rt300@0
|
23 #include "ofxPd.h"
|
rt300@0
|
24 #include "TestController.h"
|
rt300@0
|
25 #include "timeController.h"
|
rt300@0
|
26 #include "PDSynthWrapper.h"
|
rt300@0
|
27 #include "ofxTimer.h"
|
rt300@0
|
28 #include "sliderPanel.h"
|
rt300@0
|
29 //#include "testApp.h"
|
rt300@0
|
30 #include "targetSymbol.h"
|
rt300@0
|
31 #include "3Dbox.h"
|
rt300@0
|
32 #include "TextPanel.h"
|
rt300@0
|
33 #include "CountdownText.h"
|
rt300@0
|
34 #include "buttonPanel.h"
|
rt300@6
|
35 #include "ExplorePresetManager.h"
|
rt300@6
|
36
|
rt300@6
|
37
|
rt300@6
|
38 // should be called TIMED TEST MESSAGE ORGANISER ?
|
rt300@0
|
39
|
rt300@0
|
40 // event logger needs to know
|
rt300@0
|
41 // which controls were showing in what mode
|
rt300@0
|
42 // which controls were mapped to what param
|
rt300@0
|
43 // what was the target sound params
|
rt300@0
|
44 // all the updates of control movements, submit, quit etc
|
rt300@0
|
45
|
rt300@0
|
46 // this is the bit that handles mapping from UI elements to synth i.e testApp DOESNT DO THAT
|
rt300@0
|
47
|
rt300@0
|
48 // has links to panel sliders can show hide them
|
rt300@0
|
49
|
rt300@0
|
50 // controls flow of stuff
|
rt300@0
|
51
|
rt300@0
|
52 //---------------------------------------------------------------------
|
rt300@0
|
53 //---------------------------------------------------------------------
|
rt300@0
|
54 extern TimeController timeController;
|
rt300@0
|
55
|
rt300@0
|
56 extern EventLogger eventLogger;
|
rt300@0
|
57
|
rt300@6
|
58 extern ExplorePresetManager expPresetManager;
|
rt300@4
|
59
|
rt300@0
|
60 typedef boost::function<void(void)> AppModeChangeFunction;
|
rt300@0
|
61
|
rt300@0
|
62 class MessageOrganiser {
|
rt300@0
|
63 private:
|
rt300@0
|
64 AppCore* core;
|
rt300@0
|
65 //testApp* theOFApp;
|
rt300@0
|
66 PDSynthWrapper targetSynth;
|
rt300@0
|
67 PDSynthWrapper candidateSynth;
|
rt300@0
|
68
|
rt300@0
|
69 map<int,UIElement*> currentMapping; // could get more sophisticated if not 1-1 ?
|
rt300@0
|
70
|
rt300@0
|
71 SliderPanel* panel;
|
rt300@0
|
72 TimeController altPlaybackController;
|
rt300@0
|
73
|
rt300@0
|
74 TestController* testController;
|
rt300@0
|
75 Buttron* newTestButton;
|
rt300@0
|
76 //Buttron* submitButton;
|
rt300@0
|
77
|
rt300@0
|
78 ButtonPanel* bottomPanel; // shows during test : play buttons and submit
|
rt300@0
|
79 Buttron* targetPlayButton; // so we can hide target in memory test. this pointer stuff is getting out of hand
|
rt300@0
|
80 CountdownText* countdownPanel;
|
rt300@0
|
81 TargetSymbol* targetSymbol;
|
rt300@0
|
82 Leap3DBoxGL* box3D;
|
rt300@0
|
83 TextPanel* scorePanel;
|
rt300@0
|
84 TextPanel* finishPanel;
|
rt300@0
|
85 AppModeChangeFunction testAppModeChange;
|
rt300@0
|
86
|
rt300@0
|
87 //int scoreRunningTotal;
|
rt300@0
|
88 TimerID currentSoundPlayTimer;
|
rt300@0
|
89
|
rt300@0
|
90 int alternationSpeed; // ms between cand and target
|
rt300@0
|
91 bool playingAlternating;
|
rt300@0
|
92
|
rt300@0
|
93 bool okToGetLeapMidi;
|
rt300@0
|
94
|
rt300@0
|
95 void testsFinished(){
|
rt300@0
|
96 panel->hide();
|
rt300@0
|
97 bottomPanel->hide();
|
rt300@0
|
98 newTestButton->hide();
|
rt300@0
|
99
|
rt300@0
|
100 vector<int> eData;
|
rt300@0
|
101 eData.push_back(testController->getScoreRunningTotal());
|
rt300@0
|
102 eventLogger.logEvent(ALL_TESTS_COMPLETED, eData);
|
rt300@0
|
103
|
rt300@0
|
104 // TODO set final score screen txt to testController->getScoreRunningTotal()
|
rt300@0
|
105 finishPanel->show();
|
rt300@0
|
106
|
rt300@0
|
107 string user = eventLogger.getUsername();
|
rt300@0
|
108 stringstream s;
|
rt300@0
|
109 s << "Experiment completed"
|
rt300@0
|
110 << endl << endl
|
rt300@0
|
111 << "You scored: " << testController->getScoreRunningTotal() << " well done " << user << endl << endl
|
rt300@0
|
112 << "to retake test please close " << endl << endl
|
rt300@0
|
113 << "the app and restart with username<num test>";
|
rt300@0
|
114 finishPanel->setText(s.str());
|
rt300@0
|
115 // get test app to do something...
|
rt300@0
|
116
|
rt300@0
|
117 eventLogger.saveSessionToFile();
|
rt300@0
|
118 };
|
rt300@0
|
119
|
rt300@0
|
120 void setupNewTest(){
|
rt300@0
|
121 // get mapping for new test and make sure we have right controls and stuff
|
rt300@0
|
122
|
rt300@0
|
123
|
rt300@0
|
124 Test newTest = testController->goToNextTest();
|
rt300@0
|
125
|
rt300@0
|
126 // V0.2 put details about what kind of test it is
|
rt300@0
|
127 vector<int> eData;
|
rt300@0
|
128 eData.push_back(newTest.isPractice());
|
rt300@0
|
129 eData.push_back(newTest.isWithHint());
|
rt300@0
|
130 eData.push_back(newTest.isMemoryTest());
|
rt300@0
|
131 eventLogger.logEvent(NEW_TEST, eData);
|
rt300@0
|
132
|
rt300@0
|
133
|
rt300@0
|
134 vector<int> mappingIDsForChangeableParams = setSynthsUpForNewTest(newTest);
|
rt300@0
|
135
|
rt300@0
|
136 vector<UIElement*> UIElemHandles = panel->generateControls(testController->getCurrentListOfControls(), testController->getCurrentPanelType());
|
rt300@0
|
137
|
rt300@0
|
138 mapUIToNewTestParams(UIElemHandles, mappingIDsForChangeableParams);
|
rt300@0
|
139
|
rt300@0
|
140 countdownPanel->setTestTypeString(newTest.getTestTypeAdvanceWarning());
|
rt300@0
|
141
|
rt300@0
|
142
|
rt300@0
|
143 };
|
rt300@0
|
144 void startNewTest(){
|
rt300@0
|
145 Test t = testController->getCurrentTest();
|
rt300@0
|
146
|
rt300@0
|
147 countdownPanel->hide();
|
rt300@0
|
148 panel->show();
|
rt300@0
|
149 panel->setActive(true);
|
rt300@0
|
150 if(t.isWithHint()){
|
rt300@0
|
151 panel->showHint(true);
|
rt300@0
|
152 }
|
rt300@0
|
153
|
rt300@0
|
154 bottomPanel->show();
|
rt300@0
|
155 targetPlayButton->show(); // incase it was memory test
|
rt300@0
|
156 if (t.isMemoryTest()){
|
rt300@0
|
157 targetPlayButton->setLabel("Memorise!");
|
rt300@0
|
158 }else{
|
rt300@0
|
159 targetPlayButton->setLabel("Target");
|
rt300@0
|
160 }
|
rt300@0
|
161 //startAlternatingPlayback();
|
rt300@0
|
162 //timeController.scheduleEvent(boost::bind(&MessageOrganiser::sendSynthValuesAgain, this), 200);
|
rt300@0
|
163 timeController.startStopwatch();
|
rt300@0
|
164 eventLogger.logEvent(TEST_TIMER_STARTED);
|
rt300@0
|
165
|
rt300@0
|
166
|
rt300@0
|
167 if(t.getListOfControlTypes()[0] == LEAP3D){
|
rt300@0
|
168 okToGetLeapMidi = true;
|
rt300@0
|
169 }
|
rt300@0
|
170 };
|
rt300@0
|
171
|
rt300@0
|
172 vector<int> setSynthsUpForNewTest(Test newTest){
|
rt300@0
|
173 targetSynth.setAllParams(newTest.getTargetValues());
|
rt300@0
|
174 eventLogger.logEvent(TARGET_PARAM_SET, newTest.getTargetValues()); // unless something goes wrong in setAllParams
|
rt300@0
|
175
|
rt300@0
|
176 candidateSynth.setAllParams(newTest.getStartingCandidateValues());
|
rt300@0
|
177 eventLogger.logEvent(CANDIDATE_PARAM_SET,newTest.getStartingCandidateValues());
|
rt300@0
|
178
|
rt300@0
|
179 // eventLogger.logEvent(NEW_TARGET_PARAMS, vector<int> );
|
rt300@0
|
180 // eventLogger.logEvent(NEW_CANDIDATE_PARAMS, vector<int> );
|
rt300@0
|
181
|
rt300@0
|
182 vector<int> mids = candidateSynth.getMappingIDForIndices(newTest.getChangeableIndices());
|
rt300@0
|
183
|
rt300@0
|
184 eventLogger.logEvent(CANDIDATE_CHANGEABLE_IDX, newTest.getChangeableIndices());
|
rt300@0
|
185 eventLogger.logEvent(CANDIDATE_MAPPING_IDS, mids);
|
rt300@0
|
186
|
rt300@0
|
187 return mids;
|
rt300@0
|
188 };
|
rt300@0
|
189 void sendSynthValuesAgain(){
|
rt300@0
|
190 candidateSynth.sendAllParams();
|
rt300@0
|
191 targetSynth.sendAllParams();
|
rt300@0
|
192 };
|
rt300@0
|
193
|
rt300@0
|
194 // could have been cleverer. takes forever due to searching ???
|
rt300@0
|
195 void mapUIToNewTestParams(vector<UIElement*> elems, vector<int> mids){
|
rt300@0
|
196
|
rt300@0
|
197 vector<UIElement*>::iterator elit;
|
rt300@0
|
198 vector<int> typeListLog;
|
rt300@0
|
199 int i = 0;
|
rt300@0
|
200 for(elit=elems.begin(); elit<elems.end();elit++){
|
rt300@0
|
201 if ( (*elit)->getType() == XYPAD){
|
rt300@0
|
202 if(i+1 >= mids.size()){
|
rt300@0
|
203 cout << "ERROR ERROR: too many controls for mapping IDs" << endl;
|
rt300@0
|
204 }
|
rt300@0
|
205
|
rt300@0
|
206 ButtronXY* theXY = (ButtronXY*)(*elit);
|
rt300@0
|
207 mapXYToParams(theXY, mids[i], mids[i+1]);
|
rt300@0
|
208 theXY->setValueAndScale(candidateSynth.getParamValueForID(mids[i]), candidateSynth.getParamValueForID(mids[i+1]));
|
rt300@0
|
209 theXY->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i]))
|
rt300@0
|
210 ,targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i+1])));
|
rt300@0
|
211 i+=2;
|
rt300@0
|
212 typeListLog.push_back(int(XYPAD));
|
rt300@0
|
213 }else if ( (*elit)->getType() == SLIDER){
|
rt300@0
|
214 if(i >= mids.size()){
|
rt300@2
|
215
|
rt300@2
|
216 cout << "ERROR ERROR: too many controls for mapping IDs: " << mids.size() << endl;
|
rt300@0
|
217 }
|
rt300@0
|
218
|
rt300@0
|
219 ButtronSlider* theSlider = (ButtronSlider*)(*elit);
|
rt300@0
|
220 mapControlToParam((*elit), mids[i]);
|
rt300@0
|
221 theSlider->setValueAndScale(candidateSynth.getParamValueForID(mids[i]));
|
rt300@0
|
222 cout << "Hint Value " << targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])) << endl;
|
rt300@0
|
223 theSlider->setHintValue(targetSynth.getParamValueFromName(candidateSynth.getNameForMappingID(mids[i])));
|
rt300@0
|
224 i++;
|
rt300@0
|
225 typeListLog.push_back(int(SLIDER));
|
rt300@0
|
226 }else if ( (*elit)->getType() == LEAP3D ){
|
rt300@0
|
227 set3Dbox((Leap3DBoxGL*)(*elit));
|
rt300@0
|
228 // UH
|
rt300@0
|
229 string nameX = candidateSynth.getNameForMappingID(mids[i]);
|
rt300@0
|
230 box3D->setHintValue(0,targetSynth.getParamValueFromName(nameX));
|
rt300@0
|
231 box3D->setValueAndScale(0, candidateSynth.getParamValueForID(mids[i]));
|
rt300@0
|
232 i++;
|
rt300@0
|
233
|
rt300@0
|
234 string nameY = candidateSynth.getNameForMappingID(mids[i]);
|
rt300@0
|
235 box3D->setHintValue(1,targetSynth.getParamValueFromName(nameY));
|
rt300@0
|
236 box3D->setValueAndScale(1, candidateSynth.getParamValueForID(mids[i]));
|
rt300@0
|
237 i++;
|
rt300@0
|
238
|
rt300@0
|
239 string nameZ = candidateSynth.getNameForMappingID(mids[i]);
|
rt300@0
|
240 box3D->setHintValue(2,targetSynth.getParamValueFromName(nameZ));
|
rt300@0
|
241 box3D->setValueAndScale(2, candidateSynth.getParamValueForID(mids[i]));
|
rt300@0
|
242 i++;
|
rt300@0
|
243
|
rt300@0
|
244
|
rt300@0
|
245 box3D->setLabels(nameX,nameY,nameZ);
|
rt300@0
|
246 typeListLog.push_back(int(LEAP3D));
|
rt300@0
|
247
|
rt300@0
|
248 }else{
|
rt300@0
|
249 cout << "ERROR ERROR: ui type not handled my mapping function !" << endl;
|
rt300@0
|
250 }
|
rt300@0
|
251 }
|
rt300@0
|
252
|
rt300@0
|
253 eventLogger.logEvent(CONTROL_LIST,typeListLog);
|
rt300@0
|
254 };
|
rt300@0
|
255
|
rt300@0
|
256 // TODO - no, triggering playback needs to be logged
|
rt300@0
|
257 void startAlternatingPlayback(){
|
rt300@0
|
258
|
rt300@0
|
259 cout << "start alt playback" << endl;
|
rt300@0
|
260 // use our special timer to fire off play to pd
|
rt300@0
|
261 // sets off timed alternating playback
|
rt300@0
|
262
|
rt300@0
|
263 playAlternating();
|
rt300@0
|
264 playingAlternating = true;
|
rt300@0
|
265
|
rt300@0
|
266 };
|
rt300@0
|
267 void stopAlternatingPlayback(){
|
rt300@0
|
268 cout << "stop alt playback" << endl;
|
rt300@0
|
269 // kill the alternation
|
rt300@0
|
270 timeController.cancelEvent(currentSoundPlayTimer);
|
rt300@0
|
271 playingAlternating = false;
|
rt300@0
|
272 };
|
rt300@0
|
273
|
rt300@0
|
274 void playAlternating(){
|
rt300@0
|
275
|
rt300@0
|
276 static bool alt;
|
rt300@0
|
277 int nextTime;
|
rt300@0
|
278 if (alt){
|
rt300@0
|
279 targetSynth.trigger();
|
rt300@0
|
280 // flash the target thingy
|
rt300@0
|
281 targetSymbol->flash();
|
rt300@0
|
282 nextTime = alternationSpeed*1.503; // gap after target
|
rt300@0
|
283 }else{
|
rt300@0
|
284 sendSynthValuesAgain(); // and again and again
|
rt300@0
|
285 candidateSynth.trigger();
|
rt300@0
|
286 panel->flash();
|
rt300@0
|
287 nextTime = alternationSpeed;
|
rt300@0
|
288 }
|
rt300@0
|
289 alt = !alt;
|
rt300@0
|
290 candidateSynth.setNoteLength(alternationSpeed);
|
rt300@0
|
291 targetSynth.setNoteLength(alternationSpeed); // could be user alterable
|
rt300@0
|
292 currentSoundPlayTimer = timeController.scheduleEvent(boost::bind(&MessageOrganiser::playAlternating,this), nextTime);
|
rt300@0
|
293
|
rt300@0
|
294
|
rt300@0
|
295
|
rt300@0
|
296 };
|
rt300@0
|
297
|
rt300@0
|
298 void delayedShowNewTest(){
|
rt300@0
|
299 newTestButton->show();
|
rt300@0
|
300 // JUST IN CASE IT CRASHES near end...
|
rt300@0
|
301 //eventLogger.saveSessionToFile();
|
rt300@0
|
302 };
|
rt300@0
|
303 void submitSingleControl(){
|
rt300@0
|
304 // if last one
|
rt300@0
|
305 // submitPressed()
|
rt300@0
|
306
|
rt300@0
|
307 // else
|
rt300@0
|
308
|
rt300@0
|
309 // grey out that slider,
|
rt300@0
|
310 // activate next slider and show it's button (same button but moved!???)
|
rt300@0
|
311
|
rt300@0
|
312 };
|
rt300@0
|
313
|
rt300@0
|
314
|
rt300@0
|
315 void submitPressed(){
|
rt300@0
|
316
|
rt300@0
|
317 // depending on mode go to next control
|
rt300@0
|
318 // if(testController->getCurrentPanelType() == SEQUENTIAL){
|
rt300@0
|
319 // submitSingleControl();
|
rt300@0
|
320 // return;
|
rt300@0
|
321 // }
|
rt300@0
|
322 // otherwise do this other - or call
|
rt300@0
|
323
|
rt300@0
|
324 okToGetLeapMidi = false;
|
rt300@0
|
325
|
rt300@0
|
326 TimerMillisec timeTaken = timeController.stopStopwatch();
|
rt300@0
|
327 vector<int> answer = candidateSynth.getAllParamValues();
|
rt300@0
|
328
|
rt300@0
|
329 eventLogger.logEvent(SUBMIT_PRESSED, answer); //, answer, scoreRunningTotal, time taken (why not?));
|
rt300@0
|
330
|
rt300@0
|
331 TestResult result = testController->submitAnswer(answer, timeTaken); // TODO returns all the results
|
rt300@0
|
332
|
rt300@0
|
333 vector<int> logResult;
|
rt300@0
|
334 logResult.push_back(result.realDistanceToTarget*1000); // measured in milliCC !??!
|
rt300@0
|
335 logResult.push_back(result.timeTaken); // milliseconds
|
rt300@0
|
336 logResult.push_back(result.score);
|
rt300@0
|
337 logResult.push_back(result.targetBandHit);
|
rt300@0
|
338 logResult.push_back(result.timeWindowHit);
|
rt300@0
|
339
|
rt300@0
|
340 eventLogger.logEvent(DISTANCE_TIME_SCORE, logResult);
|
rt300@0
|
341
|
rt300@0
|
342
|
rt300@0
|
343 // gui stuff - different controller?
|
rt300@0
|
344 panel->setActive(false);
|
rt300@0
|
345 panel->showHint(true); // add some encouraging feedback to hint
|
rt300@0
|
346 bottomPanel->hide();
|
rt300@0
|
347
|
rt300@0
|
348 showScoreForTest(result);
|
rt300@0
|
349
|
rt300@0
|
350 stopAlternatingPlayback();
|
rt300@0
|
351
|
rt300@0
|
352 // was it the final sumbit?
|
rt300@0
|
353 if(testController->isLastTest()){
|
rt300@0
|
354 // thats it - show a final score screen etc
|
rt300@0
|
355 timeController.scheduleEvent(boost::bind(&MessageOrganiser::testsFinished, this), 500);
|
rt300@0
|
356 return;
|
rt300@0
|
357 }else{
|
rt300@0
|
358 timeController.scheduleEvent(boost::bind(&MessageOrganiser::delayedShowNewTest, this), 300);
|
rt300@0
|
359 }
|
rt300@0
|
360
|
rt300@0
|
361
|
rt300@0
|
362 };
|
rt300@0
|
363
|
rt300@0
|
364 void showScoreForTest(TestResult result){
|
rt300@0
|
365 scorePanel->setText(result.displayText);
|
rt300@0
|
366 scorePanel->show();
|
rt300@0
|
367
|
rt300@0
|
368 ofColor c;
|
rt300@0
|
369 if(result.targetBandHit == 1){
|
rt300@0
|
370 // yellow red blue
|
rt300@0
|
371 c = ofColor(255,255,0,255);
|
rt300@0
|
372 }else if(result.targetBandHit == 2){
|
rt300@0
|
373 c = ofColor(255,0,0,255);
|
rt300@0
|
374 }else if(result.targetBandHit == 3){
|
rt300@0
|
375 c = ofColor(45,45,255,255);
|
rt300@0
|
376 }else if(result.targetBandHit == 4){
|
rt300@0
|
377 c = ofColor(0,255,0,255);
|
rt300@0
|
378 }else{
|
rt300@0
|
379 c = ofColor(150,235,200,255);
|
rt300@0
|
380 }
|
rt300@0
|
381 scorePanel->setColor(c);
|
rt300@0
|
382 panel->setHintColor(c);
|
rt300@0
|
383 };
|
rt300@0
|
384
|
rt300@4
|
385 void setAllSlidersToValues(vector<int> values){
|
rt300@4
|
386 for(int i = 0; i < values.size(); i++){
|
rt300@4
|
387 setUIToParam(i, values[i]);
|
rt300@4
|
388 }
|
rt300@4
|
389 }
|
rt300@0
|
390 // we want to set UI object
|
rt300@0
|
391 void setUIToParam(int index, int value){ // e.g. from MIDI incoming, will handle both box and sliders...
|
rt300@0
|
392 // theXY->setValueAndScale(candidateSynth.getParamValueForID(mids[i]), candidateSynth.getParamValueForID(mids[i+1]));
|
rt300@0
|
393 UIElement* elem;
|
rt300@0
|
394 // get the element
|
rt300@0
|
395 if(panel->subElements.size() <= index){
|
rt300@4
|
396 cout << "ERROR: index out of range for num sliders" << endl;
|
rt300@0
|
397 return;
|
rt300@0
|
398 }
|
rt300@0
|
399 elem = panel->subElements[index];
|
rt300@0
|
400 if ( elem->getType() == SLIDER){
|
rt300@0
|
401 ButtronSlider* theSlider = (ButtronSlider*)elem;
|
rt300@0
|
402 theSlider->setValueAndScale(value);
|
rt300@0
|
403
|
rt300@0
|
404 }else{
|
rt300@0
|
405 cout << "ERROR ERROR: ui type not handled by setUIToParam!" << endl;
|
rt300@0
|
406 }
|
rt300@0
|
407
|
rt300@0
|
408 };
|
rt300@0
|
409
|
rt300@0
|
410
|
rt300@0
|
411 void mapControlToParam(UIElement* control, int mappingID){
|
rt300@0
|
412
|
rt300@0
|
413 UICallbackFunction callbackF;
|
rt300@0
|
414 callbackF = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
|
rt300@0
|
415 control->addHandler(callbackF, mappingID);
|
rt300@0
|
416 // put in our map so we can send param values to gui
|
rt300@0
|
417 currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
|
rt300@0
|
418 cout << " Mapped control to ID: " << mappingID << "Name: " << candidateSynth.getNameForMappingID(mappingID) << endl;
|
rt300@0
|
419 control->setLabel(candidateSynth.getNameForMappingID(mappingID));
|
rt300@0
|
420 };
|
rt300@0
|
421
|
rt300@0
|
422 void mapXYToParams(ButtronXY* control, int mappingIDX, int mappingIDY){
|
rt300@0
|
423 UICallbackFunction callback;
|
rt300@0
|
424
|
rt300@0
|
425 callback = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
|
rt300@0
|
426
|
rt300@0
|
427 control->addHandler(callback, mappingIDX, mappingIDY);
|
rt300@0
|
428
|
rt300@0
|
429 // put in our map so we can send param values to gui
|
rt300@0
|
430 //currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
|
rt300@0
|
431
|
rt300@0
|
432
|
rt300@0
|
433 cout << " Mapped control to XID: " << mappingIDX << "Name: " << candidateSynth.getNameForMappingID(mappingIDX) << endl;
|
rt300@0
|
434 cout << " Mapped control to YID: " << mappingIDY << "Name: " << candidateSynth.getNameForMappingID(mappingIDY) << endl;
|
rt300@0
|
435 control->setLabel(candidateSynth.getNameForMappingID(mappingIDX), candidateSynth.getNameForMappingID(mappingIDY));
|
rt300@0
|
436
|
rt300@0
|
437 };
|
rt300@0
|
438
|
rt300@0
|
439 void mapLeapToParams(ButtronXY* control, int mappingIDX, int mappingIDY, int mappingIDZ){
|
rt300@0
|
440 // UICallbackFunction callbackX;
|
rt300@0
|
441 // UICallbackFunction callbackY;
|
rt300@0
|
442 // UICallbackFunction callbackZ;
|
rt300@0
|
443 //
|
rt300@0
|
444 // callbackX = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
|
rt300@0
|
445 // callbackY = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
|
rt300@0
|
446 // callbackZ = boost::bind(&MessageOrganiser::paramChangeCallback, this, _1,_2);
|
rt300@0
|
447 //
|
rt300@0
|
448 // control->addHandler(callbackX, mappingIDX);
|
rt300@0
|
449 // control->addHandler(callbackY, mappingIDY);
|
rt300@0
|
450 //
|
rt300@0
|
451 // // put in our map so we can send param values to gui
|
rt300@0
|
452 // //currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
|
rt300@0
|
453 //
|
rt300@0
|
454 //
|
rt300@0
|
455 // cout << " Mapped control to XID: " << mappingIDX << "Name: " << candidateSynth.getNameForMappingID(mappingIDX) << endl;
|
rt300@0
|
456 // cout << " Mapped control to YID: " << mappingIDY << "Name: " << candidateSynth.getNameForMappingID(mappingIDY) << endl;
|
rt300@0
|
457 // control->setLabel(candidateSynth.getNameForMappingID(mappingIDX), candidateSynth.getNameForMappingID(mappingIDY));
|
rt300@0
|
458
|
rt300@0
|
459 };
|
rt300@0
|
460
|
rt300@0
|
461 void mapControlToParam(UIElement* control, string paramName){
|
rt300@0
|
462 // get mapping ID from synth
|
rt300@0
|
463 int mappingID = candidateSynth.getMappingIDForName(paramName);
|
rt300@0
|
464 mapControlToParam(control, mappingID);
|
rt300@0
|
465 control->setLabel(paramName);
|
rt300@0
|
466 };
|
rt300@0
|
467 public:
|
rt300@0
|
468 void init(AppCore* aCore, TestController* tc){
|
rt300@0
|
469 // set PD core...
|
rt300@0
|
470
|
rt300@0
|
471 core = aCore;
|
rt300@0
|
472 targetSynth.init(aCore,"targetSynth");
|
rt300@0
|
473 candidateSynth.init(aCore,"candidateSynth");
|
rt300@0
|
474
|
rt300@0
|
475 testController = tc;
|
rt300@0
|
476 currentSoundPlayTimer = -1;
|
rt300@0
|
477 okToGetLeapMidi = false;
|
rt300@0
|
478
|
rt300@0
|
479 alternationSpeed = 200;
|
rt300@0
|
480
|
rt300@0
|
481 candidateSynth.setNoteLength(alternationSpeed);
|
rt300@0
|
482 targetSynth.setNoteLength(alternationSpeed);
|
rt300@0
|
483
|
rt300@0
|
484 playingAlternating = false;
|
rt300@0
|
485 };
|
rt300@0
|
486 void setNewTestButton(Buttron * ntb){
|
rt300@0
|
487 newTestButton = ntb;
|
rt300@0
|
488 };
|
rt300@0
|
489 void set3Dbox(Leap3DBoxGL* box){
|
rt300@0
|
490 box3D = box;
|
rt300@0
|
491 };
|
rt300@0
|
492 void setBottomPanel(ButtonPanel * ntb){
|
rt300@0
|
493 bottomPanel = ntb;
|
rt300@0
|
494 };
|
rt300@0
|
495 void setControlPanel(SliderPanel* p){
|
rt300@0
|
496 panel = p;
|
rt300@0
|
497
|
rt300@0
|
498 };
|
rt300@0
|
499 void setCountdownPanel(CountdownText* cd){
|
rt300@0
|
500 countdownPanel = cd;
|
rt300@0
|
501 };
|
rt300@0
|
502 void setTargetSymbol(TargetSymbol* ts){
|
rt300@0
|
503 targetSymbol = ts;
|
rt300@0
|
504 };
|
rt300@0
|
505 void setScorePanel(TextPanel* tp){
|
rt300@0
|
506 scorePanel = tp;
|
rt300@0
|
507 };
|
rt300@0
|
508 void setFinishPanel(TextPanel* fp){
|
rt300@0
|
509 finishPanel = fp;
|
rt300@0
|
510 }
|
rt300@0
|
511 void setTargetButton(Buttron* tb){
|
rt300@0
|
512 targetPlayButton = tb;
|
rt300@0
|
513 }
|
rt300@0
|
514 int getScore(){
|
rt300@0
|
515 return testController->getScoreRunningTotal();
|
rt300@0
|
516 };
|
rt300@0
|
517
|
rt300@0
|
518 pair<int,int> getTime(){
|
rt300@0
|
519 TimerMillisec tms = timeController.getStopwatchElapsedTime();
|
rt300@0
|
520 int s = int(tms/1000);
|
rt300@0
|
521 int hs = int((tms%1000)/10);
|
rt300@0
|
522 pair<int,int> p(s,hs);
|
rt300@0
|
523 return p;
|
rt300@0
|
524 };
|
rt300@0
|
525 void countdownToNewTest(){
|
rt300@0
|
526
|
rt300@0
|
527 panel->hide();
|
rt300@0
|
528 panel->setActive(false);
|
rt300@0
|
529 scorePanel->hide();
|
rt300@0
|
530 bottomPanel->hide();
|
rt300@0
|
531 newTestButton->hide();
|
rt300@0
|
532
|
rt300@0
|
533 // set up stuff
|
rt300@0
|
534 setupNewTest();
|
rt300@0
|
535 eventLogger.logEvent(COUNTDOWN_INITIATED);
|
rt300@0
|
536
|
rt300@0
|
537 countdownPanel->showAndStart(3);
|
rt300@0
|
538
|
rt300@0
|
539 timeController.scheduleEvent(boost::bind(&MessageOrganiser::startNewTest, this), 3000);
|
rt300@0
|
540
|
rt300@0
|
541 };
|
rt300@0
|
542 void sendToGUI(vector<int> paramsToMap){
|
rt300@0
|
543 // look up these ids in mapping table
|
rt300@0
|
544 };
|
rt300@0
|
545 void saveGoodTest(Test t){
|
rt300@0
|
546
|
rt300@0
|
547 };
|
rt300@0
|
548 void playTargetButtonPressed(){
|
rt300@0
|
549
|
rt300@0
|
550 static int numPlays = 3;
|
rt300@0
|
551
|
rt300@0
|
552 Test* t = testController->getCurrentTestPtr();
|
rt300@0
|
553 if (!t->checkTargetPlaysRemaining()){
|
rt300@0
|
554 cout << t->getTargetPlaysLeft() << endl;
|
rt300@0
|
555
|
rt300@0
|
556 sendSynthValuesAgain();
|
rt300@0
|
557 targetSynth.trigger();
|
rt300@0
|
558 eventLogger.logEvent(TARGET_PLAYED);
|
rt300@0
|
559 targetPlayButton->hide();
|
rt300@0
|
560 return;
|
rt300@0
|
561
|
rt300@0
|
562 }
|
rt300@0
|
563 cout << t->getTargetPlaysLeft() << endl;
|
rt300@0
|
564
|
rt300@0
|
565 sendSynthValuesAgain();
|
rt300@0
|
566 targetSynth.trigger();
|
rt300@0
|
567 eventLogger.logEvent(TARGET_PLAYED);
|
rt300@0
|
568
|
rt300@0
|
569 return;
|
rt300@0
|
570 }
|
rt300@0
|
571 void playCandidateButtonPressed(){
|
rt300@0
|
572 //
|
rt300@0
|
573 }
|
rt300@0
|
574 void buttonPressCallback(int mappingID, int value){
|
rt300@0
|
575 if(mappingID == VOLUME_CHANGE_ID){
|
rt300@0
|
576 targetSynth.sendVolume(value);
|
rt300@0
|
577 candidateSynth.sendVolume(value);
|
rt300@0
|
578
|
rt300@0
|
579 }
|
rt300@0
|
580 if(mappingID == SPEED_CHANGE_ID){
|
rt300@0
|
581 alternationSpeed = 2*(140 - value);
|
rt300@0
|
582 vector<int> eData;
|
rt300@0
|
583 eData.push_back(alternationSpeed);
|
rt300@0
|
584 eventLogger.logEvent(SPEED_CHANGED, eData);
|
rt300@0
|
585 }
|
rt300@0
|
586 if(mappingID == NEW_TEST_ID){
|
rt300@0
|
587 countdownToNewTest();
|
rt300@0
|
588 return;
|
rt300@0
|
589 }
|
rt300@0
|
590 if (mappingID == START_ALTERNATE_ID){
|
rt300@0
|
591 if(!playingAlternating){
|
rt300@0
|
592 startAlternatingPlayback();
|
rt300@0
|
593
|
rt300@0
|
594 }else{
|
rt300@0
|
595 stopAlternatingPlayback();
|
rt300@0
|
596 }
|
rt300@0
|
597 return;
|
rt300@0
|
598 }
|
rt300@0
|
599 if(mappingID == GOOD_TEST_ID){
|
rt300@0
|
600 Test t = testController->getCurrentTest();
|
rt300@0
|
601 saveGoodTest(t);
|
rt300@0
|
602 }
|
rt300@0
|
603 if (mappingID == RANDOMISE_TARGET_ID){ // bleyeueurrrr
|
rt300@0
|
604 targetSynth.randomiseParams();
|
rt300@0
|
605 return;
|
rt300@0
|
606 }
|
rt300@0
|
607 if (mappingID == TRIGGER_TARGET_ID){
|
rt300@0
|
608 playTargetButtonPressed();
|
rt300@0
|
609
|
rt300@0
|
610 }
|
rt300@0
|
611 if (mappingID == TRIGGER_CANDIDATE_ID){
|
rt300@0
|
612 // log event
|
rt300@0
|
613 sendSynthValuesAgain();
|
rt300@0
|
614 candidateSynth.trigger();
|
rt300@0
|
615 eventLogger.logEvent(CANDIDATE_PLAYED);
|
rt300@0
|
616 // flash panel?
|
rt300@0
|
617 panel->flash();
|
rt300@0
|
618 return;
|
rt300@0
|
619 }
|
rt300@0
|
620 if (mappingID == SUBMIT_CANDIDATE){
|
rt300@0
|
621 // log event
|
rt300@0
|
622 submitPressed();
|
rt300@0
|
623
|
rt300@0
|
624 return;
|
rt300@0
|
625 }
|
rt300@0
|
626 if (mappingID == CRAP_TEST_ID){
|
rt300@0
|
627 // this is rubbish! send a log of target values, and mapping ids
|
rt300@0
|
628 vector<int> data;
|
rt300@0
|
629 vector<int> tvals = targetSynth.getAllParamValues();
|
rt300@0
|
630 vector<int> pidx = testController->getCurrentChangeableParams();
|
rt300@0
|
631 data.insert(data.end(), tvals.begin(), tvals.end());
|
rt300@0
|
632 data.insert(data.end(), pidx.begin(), pidx.end());
|
rt300@0
|
633
|
rt300@0
|
634 eventLogger.logEvent(CRAP_TEST, data);
|
rt300@0
|
635 }
|
rt300@0
|
636 if(mappingID == SHOW_HIDE_PANEL){
|
rt300@0
|
637 static bool showing;
|
rt300@0
|
638
|
rt300@0
|
639 if(showing){
|
rt300@0
|
640 cout << " showing"<<endl;
|
rt300@0
|
641
|
rt300@0
|
642 panel->show();
|
rt300@0
|
643
|
rt300@0
|
644 }else{
|
rt300@0
|
645 cout << " hiding"<<endl;
|
rt300@0
|
646 panel->hide();
|
rt300@0
|
647 }
|
rt300@0
|
648 showing = !showing;
|
rt300@0
|
649 }
|
rt300@0
|
650 if(mappingID == SHOW_HIDE_HINT){
|
rt300@0
|
651 static bool showingHint;
|
rt300@0
|
652 if(showingHint){
|
rt300@0
|
653 panel->showHint(false);
|
rt300@0
|
654 showingHint = false;
|
rt300@0
|
655 }else{
|
rt300@0
|
656 panel->showHint(true);
|
rt300@0
|
657 showingHint = true;
|
rt300@0
|
658 }
|
rt300@0
|
659 }
|
rt300@4
|
660 if(mappingID == SAVE_PRESET_HIT){
|
rt300@6
|
661 expPresetManager.savePreset("blah", candidateSynth.getAllParamValues());
|
rt300@4
|
662
|
rt300@4
|
663 }
|
rt300@4
|
664 if(mappingID == RECALL_PRESET_HIT){
|
rt300@4
|
665
|
rt300@4
|
666 loadPreset("blah");
|
rt300@6
|
667 //candidateSynth.startMetronome();
|
rt300@4
|
668
|
rt300@4
|
669 }
|
rt300@4
|
670 }
|
rt300@4
|
671 void loadPreset(string pname){
|
rt300@4
|
672
|
rt300@6
|
673 vector<int> values = expPresetManager.recallPreset(pname);
|
rt300@5
|
674 if (values.size()){
|
rt300@4
|
675 candidateSynth.setAllParams(values);
|
rt300@4
|
676 setAllSlidersToValues(values);
|
rt300@5
|
677 }else{
|
rt300@5
|
678 cout << "ERROR, no preset found" << endl;
|
rt300@5
|
679 }
|
rt300@0
|
680 }
|
rt300@0
|
681 // called from UI
|
rt300@0
|
682 void paramChangeCallback(int mappingID, int value){
|
rt300@0
|
683 candidateSynth.paramChangeCallback(mappingID, value);
|
rt300@0
|
684 vector<int> evtData;
|
rt300@0
|
685 evtData.push_back(mappingID); // or just index?
|
rt300@0
|
686 evtData.push_back(value);
|
rt300@0
|
687
|
rt300@0
|
688 eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
|
rt300@0
|
689 };
|
rt300@0
|
690
|
rt300@0
|
691 // could template for ui element type??
|
rt300@0
|
692 void mapButtonToAction(UIElement* control, int mappingID){
|
rt300@0
|
693 UICallbackFunction callbackF;
|
rt300@0
|
694 callbackF = boost::bind(&MessageOrganiser::buttonPressCallback, this, _1,_2);
|
rt300@0
|
695 control->addHandler(callbackF, mappingID);
|
rt300@0
|
696 currentMapping.insert(std::pair<int,UIElement*>(mappingID,control));
|
rt300@0
|
697 }
|
rt300@0
|
698
|
rt300@0
|
699
|
rt300@0
|
700 void midiFromLeap(int ctl_num, int ctl_val){
|
rt300@0
|
701
|
rt300@0
|
702
|
rt300@0
|
703 if (!okToGetLeapMidi){
|
rt300@0
|
704 return;
|
rt300@0
|
705 }
|
rt300@2
|
706
|
rt300@0
|
707
|
rt300@0
|
708 Test *theTest = testController->getCurrentTestPtr();
|
rt300@0
|
709 if (theTest == NULL) return;
|
rt300@0
|
710
|
rt300@2
|
711
|
rt300@0
|
712
|
rt300@0
|
713
|
rt300@2
|
714
|
rt300@0
|
715 vector<int> ci = theTest->getChangeableIndices();
|
rt300@0
|
716 vector<int> mids = candidateSynth.getMappingIDForIndices(ci);
|
rt300@0
|
717 if (ctl_num >= mids.size() || ctl_num < 0) return;
|
rt300@0
|
718
|
rt300@0
|
719 candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val);
|
rt300@0
|
720
|
rt300@3
|
721 setUIToParam(ctl_num, ctl_val);
|
rt300@2
|
722
|
rt300@0
|
723 vector<int> evtData;
|
rt300@0
|
724 evtData.push_back(mids[ctl_num]); // or just index?
|
rt300@0
|
725 evtData.push_back(ctl_val);
|
rt300@0
|
726
|
rt300@0
|
727 eventLogger.logEvent(CANDIDATE_PARAM_ADJUSTED, evtData);
|
rt300@0
|
728 // also call UI object
|
rt300@0
|
729 // get mapping ID for
|
rt300@0
|
730 // setUIToParam(ctl_num, ctl_val);
|
rt300@0
|
731 }
|
rt300@3
|
732 // void setSlidersFromLeap(int i, int val){
|
rt300@3
|
733 // ButtronSlider* theSlider = (ButtronSlider*)panel->getSlider(i);
|
rt300@3
|
734 // theSlider->setValueAndScale(val);
|
rt300@3
|
735 // }
|
rt300@3
|
736
|
rt300@3
|
737
|
rt300@3
|
738
|
rt300@3
|
739 void setSlidersToTarget(){
|
rt300@3
|
740 // this will actually show sliders with target vals - for "memorisation" purposes mwa heh heh
|
rt300@3
|
741 // get target values
|
rt300@3
|
742 // set ui
|
rt300@3
|
743 vector<int> vals = targetSynth.getAllParamValues();
|
rt300@3
|
744 for(int i=1; i < vals.size(); i++){
|
rt300@3
|
745 setUIToParam(i, vals[i]);
|
rt300@3
|
746 }
|
rt300@2
|
747 }
|
rt300@0
|
748
|
rt300@0
|
749 };
|
rt300@0
|
750
|