f@5
|
1 /*
|
f@5
|
2
|
f@5
|
3 Copyright (C) 2016 Queen Mary University of London
|
f@5
|
4 Author: Fiore Martin
|
f@5
|
5
|
f@5
|
6 This file is part of Collidoscope.
|
f@5
|
7
|
f@5
|
8 Collidoscope is free software: you can redistribute it and/or modify
|
f@5
|
9 it under the terms of the GNU General Public License as published by
|
f@5
|
10 the Free Software Foundation, either version 3 of the License, or
|
f@5
|
11 (at your option) any later version.
|
f@5
|
12
|
f@5
|
13 This program is distributed in the hope that it will be useful,
|
f@5
|
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@5
|
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@5
|
16 GNU General Public License for more details.
|
f@5
|
17
|
f@5
|
18 You should have received a copy of the GNU General Public License
|
f@5
|
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@5
|
20 */
|
f@5
|
21
|
f@6
|
22
|
f@0
|
23 #include "cinder/app/App.h"
|
f@0
|
24 #include "cinder/app/RendererGl.h"
|
f@0
|
25 #include "cinder/gl/gl.h"
|
f@0
|
26 #include "cinder/Exception.h"
|
f@6
|
27 #include <stdexcept>
|
f@0
|
28
|
f@0
|
29
|
f@0
|
30 #include "Config.h"
|
f@0
|
31 #include "Wave.h"
|
f@0
|
32 #include "DrawInfo.h"
|
f@0
|
33 #include "Log.h"
|
f@0
|
34 #include "AudioEngine.h"
|
f@0
|
35 #include "Oscilloscope.h"
|
f@0
|
36 #include "Messages.h"
|
f@0
|
37 #include "MIDI.h"
|
f@0
|
38
|
f@0
|
39 using namespace ci;
|
f@0
|
40 using namespace ci::app;
|
f@0
|
41
|
f@0
|
42 using namespace std;
|
f@0
|
43
|
f@0
|
44
|
f@0
|
45 class CollidoscopeApp : public App {
|
f@0
|
46 public:
|
f@0
|
47
|
f@5
|
48 void setup() override;
|
f@0
|
49 void setupGraphics();
|
f@0
|
50
|
f@6
|
51 /** Receives MIDI command messages from MIDI thread */
|
f@0
|
52 void receiveCommands();
|
f@6
|
53 /** Prints command line usage */
|
f@6
|
54 void usage();
|
f@0
|
55
|
f@5
|
56 void keyDown( KeyEvent event ) override;
|
f@5
|
57 void update() override;
|
f@5
|
58 void draw() override;
|
f@0
|
59 void resize() override;
|
f@0
|
60
|
f@5
|
61 Config mConfig;
|
f@0
|
62 collidoscope::MIDI mMIDI;
|
f@0
|
63 AudioEngine mAudioEngine;
|
f@5
|
64
|
f@0
|
65 array< shared_ptr< Wave >, NUM_WAVES > mWaves;
|
f@0
|
66 array< shared_ptr< DrawInfo >, NUM_WAVES > mDrawInfos;
|
f@0
|
67 array< shared_ptr< Oscilloscope >, NUM_WAVES > mOscilloscopes;
|
f@16
|
68 // buffer to read the WAVE_* messages as a new wave gets recorded
|
f@0
|
69 array< RecordWaveMsg*, NUM_WAVES> mRecordWaveMessageBuffers;
|
f@16
|
70 //buffer to read the TRIGGER_* messages as the pgranulars play
|
f@0
|
71 array< vector< CursorTriggerMsg >, NUM_WAVES > mCursorTriggerMessagesBuffers;
|
f@0
|
72
|
f@0
|
73 double mSecondsPerChunk;
|
f@0
|
74
|
f@0
|
75 ~CollidoscopeApp();
|
f@0
|
76
|
f@0
|
77 };
|
f@0
|
78
|
f@0
|
79
|
f@0
|
80 void CollidoscopeApp::setup()
|
f@0
|
81 {
|
f@0
|
82 hideCursor();
|
f@0
|
83 /* setup is logged: setup steps and errors */
|
f@0
|
84
|
f@0
|
85 /*try {
|
f@0
|
86 mConfig.loadFromFile( "./collidoscope_config.xml" );
|
f@0
|
87 }
|
f@0
|
88 catch ( const Exception &e ){
|
f@0
|
89 logError( string("Exception loading config from file:") + e.what() );
|
f@0
|
90 }*/
|
f@0
|
91
|
f@0
|
92 // setup buffers to read messages from audio thread
|
f@0
|
93 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
94 mRecordWaveMessageBuffers[i] = new RecordWaveMsg[mConfig.getNumChunks()];
|
f@0
|
95 mCursorTriggerMessagesBuffers[i].reserve( mConfig.getCursorTriggerMessageBufSize() );
|
f@0
|
96 }
|
f@0
|
97
|
f@0
|
98 mAudioEngine.setup( mConfig );
|
f@0
|
99
|
f@0
|
100 setupGraphics();
|
f@0
|
101
|
f@0
|
102 mSecondsPerChunk = mConfig.getWaveLen() / mConfig.getNumChunks();
|
f@0
|
103
|
f@0
|
104 try {
|
f@0
|
105 mMIDI.setup( mConfig );
|
f@0
|
106 }
|
f@0
|
107 catch ( const collidoscope::MIDIException &e ){
|
f@0
|
108 logError( string( "Exception opening MIDI input device: " ) + e.getMessage() );
|
f@0
|
109 }
|
f@0
|
110
|
f@0
|
111 }
|
f@0
|
112
|
f@0
|
113 void CollidoscopeApp::setupGraphics()
|
f@0
|
114 {
|
f@0
|
115 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
116
|
f@0
|
117 mDrawInfos[i] = make_shared< DrawInfo >( i );
|
f@0
|
118 mWaves[i] = make_shared< Wave >(mConfig.getNumChunks(), mConfig.getWaveSelectionColor(i) );
|
f@0
|
119 mOscilloscopes[i] = make_shared< Oscilloscope >( mAudioEngine.getAudioOutputBuffer( i ).getNumFrames() / mConfig.getOscilloscopeNumPointsDivider() );
|
f@0
|
120
|
f@0
|
121 }
|
f@0
|
122 }
|
f@0
|
123
|
f@0
|
124 void CollidoscopeApp::keyDown( KeyEvent event )
|
f@0
|
125 {
|
f@0
|
126 char c = event.getChar();
|
f@0
|
127
|
f@9
|
128 const size_t waveIdx = 0;
|
f@9
|
129
|
f@0
|
130 switch (c){
|
f@0
|
131 case 'r' :
|
f@9
|
132 mAudioEngine.record( waveIdx );
|
f@0
|
133 break;
|
f@0
|
134
|
f@0
|
135 case 'w': {
|
f@6
|
136
|
f@9
|
137 mWaves[waveIdx]->getSelection().setSize(mWaves[waveIdx]->getSelection().getSize() + 1);
|
f@0
|
138
|
f@9
|
139 size_t numSelectionChunks = mWaves[waveIdx]->getSelection().getSize();
|
f@0
|
140 // how many samples in one selection ?
|
f@0
|
141 size_t selectionSize = numSelectionChunks * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@0
|
142
|
f@9
|
143 mAudioEngine.setSelectionSize(waveIdx, selectionSize);
|
f@0
|
144 };
|
f@0
|
145 break;
|
f@0
|
146
|
f@0
|
147 case 's': {
|
f@0
|
148
|
f@9
|
149 mWaves[waveIdx]->getSelection().setSize( mWaves[waveIdx]->getSelection().getSize() - 1 );
|
f@0
|
150
|
f@9
|
151 size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() *(mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@9
|
152 mAudioEngine.setSelectionSize( waveIdx, selectionSize );
|
f@0
|
153 };
|
f@0
|
154 break;
|
f@0
|
155
|
f@0
|
156 case 'd': {
|
f@0
|
157
|
f@9
|
158 size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
f@9
|
159 mWaves[waveIdx]->getSelection().setStart( selectionStart + 1 );
|
f@0
|
160
|
f@9
|
161 selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
f@9
|
162 mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
163 };
|
f@0
|
164
|
f@0
|
165 break;
|
f@0
|
166
|
f@0
|
167 case 'a': {
|
f@9
|
168 size_t selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
f@0
|
169
|
f@0
|
170 if ( selectionStart == 0 )
|
f@0
|
171 return;
|
f@0
|
172
|
f@9
|
173 mWaves[waveIdx]->getSelection().setStart( selectionStart - 1 );
|
f@0
|
174
|
f@9
|
175 selectionStart = mWaves[waveIdx]->getSelection().getStart();
|
f@0
|
176
|
f@9
|
177 mAudioEngine.setSelectionStart( waveIdx, selectionStart * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
178 };
|
f@0
|
179 break;
|
f@0
|
180
|
f@0
|
181 case 'f':
|
f@0
|
182 setFullScreen( !isFullScreen() );
|
f@0
|
183 break;
|
f@0
|
184
|
f@0
|
185 case ' ': {
|
f@0
|
186 static bool isOn = false;
|
f@0
|
187 isOn = !isOn;
|
f@0
|
188 if ( isOn ){
|
f@9
|
189 mAudioEngine.loopOn( waveIdx );
|
f@0
|
190 }
|
f@0
|
191 else{
|
f@9
|
192 mAudioEngine.loopOff( waveIdx );
|
f@0
|
193 }
|
f@0
|
194 };
|
f@0
|
195 break;
|
f@0
|
196
|
f@0
|
197 case '9': {
|
f@9
|
198 int c = mWaves[waveIdx]->getSelection().getParticleSpread();
|
f@0
|
199 if ( c == 1 )
|
f@0
|
200 return;
|
f@0
|
201 else
|
f@0
|
202 c -= 1;
|
f@0
|
203
|
f@9
|
204 mAudioEngine.setGrainDurationCoeff( waveIdx, c );
|
f@9
|
205 mWaves[waveIdx]->getSelection().setParticleSpread( float( c ) );
|
f@9
|
206
|
f@0
|
207 }; break;
|
f@0
|
208
|
f@0
|
209 case '0': {
|
f@9
|
210 int c = mWaves[waveIdx]->getSelection().getParticleSpread();
|
f@0
|
211 if ( c == 8 )
|
f@0
|
212 return;
|
f@0
|
213 else
|
f@0
|
214 c += 1;
|
f@0
|
215
|
f@9
|
216 mAudioEngine.setGrainDurationCoeff( waveIdx, c );
|
f@9
|
217 mWaves[waveIdx]->getSelection().setParticleSpread( float( c ) );
|
f@0
|
218 }; break;
|
f@0
|
219 }
|
f@0
|
220
|
f@0
|
221 }
|
f@0
|
222
|
f@0
|
223 void CollidoscopeApp::update()
|
f@0
|
224 {
|
f@0
|
225 // check incoming commands
|
f@0
|
226 receiveCommands();
|
f@0
|
227
|
f@0
|
228 // check new wave chunks from recorder buffer
|
f@0
|
229 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
230 size_t availableRead = mAudioEngine.getRecordWaveAvailable( i );
|
f@0
|
231 mAudioEngine.readRecordWave( i, mRecordWaveMessageBuffers[i], availableRead );
|
f@0
|
232
|
f@0
|
233 for ( size_t msgIndex = 0; msgIndex < availableRead; msgIndex++ ){
|
f@0
|
234 const RecordWaveMsg & msg = mRecordWaveMessageBuffers[i][msgIndex];
|
f@0
|
235
|
f@0
|
236 if ( msg.cmd == Command::WAVE_CHUNK ){
|
f@0
|
237 mWaves[i]->setChunk( msg.index, msg.arg1, msg.arg2 );
|
f@0
|
238 }
|
f@0
|
239 else if ( msg.cmd == Command::WAVE_START ){
|
f@0
|
240 mWaves[i]->reset( true ); // reset only chunks but leave selection
|
f@0
|
241 }
|
f@0
|
242
|
f@0
|
243 }
|
f@0
|
244 }
|
f@0
|
245
|
f@0
|
246 // check if new cursors have been triggered
|
f@0
|
247 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
248
|
f@0
|
249 mAudioEngine.checkCursorTriggers( i, mCursorTriggerMessagesBuffers[i] );
|
f@0
|
250 for ( auto & trigger : mCursorTriggerMessagesBuffers[i] ){
|
f@0
|
251 const int nodeID = trigger.synthID;
|
f@0
|
252
|
f@0
|
253 switch ( trigger.cmd ){
|
f@0
|
254
|
f@0
|
255 case Command::TRIGGER_UPDATE: {
|
f@0
|
256 mWaves[i]->setCursorPos( nodeID, mWaves[i]->getSelection().getStart(), *mDrawInfos[i] );
|
f@0
|
257 };
|
f@0
|
258 break;
|
f@0
|
259
|
f@0
|
260 case Command::TRIGGER_END: {
|
f@0
|
261 mWaves[i]->removeCursor( nodeID );
|
f@0
|
262 };
|
f@0
|
263 break;
|
f@0
|
264
|
f@0
|
265 }
|
f@0
|
266
|
f@0
|
267 }
|
f@0
|
268 mCursorTriggerMessagesBuffers[i].clear();
|
f@0
|
269 }
|
f@0
|
270
|
f@0
|
271 // update cursors
|
f@0
|
272 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
273 mWaves[i]->update( mSecondsPerChunk, *mDrawInfos[i] );
|
f@0
|
274 }
|
f@0
|
275
|
f@0
|
276 // update oscilloscope
|
f@0
|
277
|
f@0
|
278 for ( size_t i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
279 const audio::Buffer &audioOutBuffer = mAudioEngine.getAudioOutputBuffer( i );
|
f@0
|
280 // one oscilloscope sample
|
f@0
|
281
|
f@0
|
282 for ( size_t j = 0; j < mOscilloscopes[i]->getNumPoints(); j++ ){
|
f@0
|
283 mOscilloscopes[i]->setPoint( j, audioOutBuffer.getData()[j], *mDrawInfos[i] );
|
f@0
|
284 }
|
f@0
|
285 }
|
f@0
|
286
|
f@0
|
287
|
f@0
|
288
|
f@0
|
289 }
|
f@0
|
290
|
f@0
|
291 void CollidoscopeApp::draw()
|
f@0
|
292 {
|
f@5
|
293 gl::clear( Color( 0, 0, 0 ) );
|
f@0
|
294
|
f@0
|
295 for ( int i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
296 if ( i == 1 ){
|
f@0
|
297 /* for the upper wave flip the x over the center of the screen which is
|
f@0
|
298 the composition of rotate on the y-axis and translate by -screenwidth*/
|
f@0
|
299 gl::pushModelMatrix();
|
f@0
|
300 gl::rotate( float(M_PI), ci::vec3( 0, 1, 0 ) );
|
f@0
|
301 gl::translate( float( -getWindowWidth() ), 0.0f );
|
f@0
|
302 mOscilloscopes[i]->draw();
|
f@0
|
303 mWaves[i]->draw( *mDrawInfos[i] );
|
f@0
|
304 gl::popModelMatrix();
|
f@0
|
305 }
|
f@0
|
306 else{
|
f@0
|
307
|
f@0
|
308 mOscilloscopes[i]->draw();
|
f@0
|
309 mWaves[i]->draw( *mDrawInfos[i] );
|
f@0
|
310 }
|
f@0
|
311 }
|
f@0
|
312 }
|
f@0
|
313
|
f@0
|
314 void CollidoscopeApp::resize()
|
f@0
|
315 {
|
f@0
|
316 App::resize();
|
f@0
|
317
|
f@0
|
318 for ( int i = 0; i < NUM_WAVES; i++ ){
|
f@0
|
319 // reset the drawing information with the new windows size and same shrink factor
|
f@0
|
320 mDrawInfos[i]->reset( getWindow()->getBounds(), 3.0f / 5.0f );
|
f@0
|
321
|
f@0
|
322 /* reset the oscilloscope points to zero */
|
f@0
|
323 for ( int j = 0; j < mOscilloscopes[i]->getNumPoints(); j++ ){
|
f@0
|
324 mOscilloscopes[i]->setPoint(j, 0.0f, *mDrawInfos[i] );
|
f@0
|
325 }
|
f@0
|
326 }
|
f@0
|
327 }
|
f@0
|
328
|
f@0
|
329
|
f@0
|
330
|
f@0
|
331 void CollidoscopeApp::receiveCommands()
|
f@0
|
332 {
|
f@0
|
333 // check new midi messages
|
f@0
|
334 static std::vector<collidoscope::MIDIMessage> midiMessages;
|
f@0
|
335 mMIDI.checkMessages( midiMessages );
|
f@0
|
336
|
f@0
|
337
|
f@0
|
338 for ( auto &m : midiMessages ){
|
f@0
|
339
|
f@0
|
340 const size_t waveIdx = mConfig.getWaveForMIDIChannel( m.getChannel() );
|
f@0
|
341 if ( waveIdx >= NUM_WAVES )
|
f@0
|
342 continue;
|
f@0
|
343
|
f@0
|
344 if ( m.getVoice() == collidoscope::MIDIMessage::Voice::eNoteOn ){
|
f@0
|
345 int midiNote = m.getData_1();
|
f@0
|
346 mAudioEngine.noteOn( waveIdx, midiNote );
|
f@0
|
347 }
|
f@0
|
348 else if ( m.getVoice() == collidoscope::MIDIMessage::Voice::eNoteOff ){
|
f@0
|
349 int midiNote = m.getData_1();
|
f@0
|
350 mAudioEngine.noteOff( waveIdx, midiNote );
|
f@0
|
351 }
|
f@0
|
352 else if ( m.getVoice() == collidoscope::MIDIMessage::Voice::ePitchBend ){
|
f@0
|
353 const uint16_t MSB = m.getData_2() << 7;
|
f@0
|
354 uint16_t value = m.getData_1(); // LSB
|
f@0
|
355
|
f@0
|
356 value |= MSB;
|
f@0
|
357
|
f@0
|
358
|
f@18
|
359 // value ranges from 0 to 149. check boundaries in case sensor gives bad values
|
f@18
|
360 if ( value > 149 ){ // FIXME can use wave.size()
|
f@0
|
361 continue;
|
f@0
|
362 }
|
f@0
|
363
|
f@0
|
364 size_t startChunk = value;
|
f@0
|
365
|
f@0
|
366 const size_t selectionSizeBeforeStartUpdate = mWaves[waveIdx]->getSelection().getSize();
|
f@0
|
367 mWaves[waveIdx]->getSelection().setStart( startChunk );
|
f@0
|
368
|
f@0
|
369 mAudioEngine.setSelectionStart( waveIdx, startChunk * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
370
|
f@0
|
371 const size_t newSelectionSize = mWaves[waveIdx]->getSelection().getSize();
|
f@0
|
372 if ( selectionSizeBeforeStartUpdate != newSelectionSize ){
|
f@0
|
373 mAudioEngine.setSelectionSize( waveIdx, newSelectionSize * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks()) );
|
f@0
|
374 }
|
f@0
|
375
|
f@0
|
376
|
f@0
|
377 }
|
f@0
|
378 else if ( m.getVoice() == collidoscope::MIDIMessage::Voice::eControlChange ){
|
f@0
|
379
|
f@0
|
380 switch ( m.getData_1() ){ //controller number
|
f@0
|
381 case 1: { // selection size
|
f@0
|
382 const size_t midiVal = m.getData_2();
|
f@0
|
383 size_t numSelectionChunks = ci::lmap<size_t>( midiVal, 0, 127, 1, mConfig.getMaxSelectionNumChunks() );
|
f@0
|
384
|
f@0
|
385 mWaves[waveIdx]->getSelection().setSize( numSelectionChunks );
|
f@0
|
386
|
f@0
|
387 // how many samples in one selection ?
|
f@5
|
388 size_t selectionSize = mWaves[waveIdx]->getSelection().getSize() * (mConfig.getWaveLen() * mAudioEngine.getSampleRate() / mConfig.getNumChunks());
|
f@0
|
389 mAudioEngine.setSelectionSize( waveIdx, selectionSize );
|
f@0
|
390
|
f@0
|
391 };
|
f@0
|
392 break;
|
f@0
|
393
|
f@0
|
394 case 4: { // loop on off
|
f@0
|
395 unsigned char midiVal = m.getData_2();
|
f@0
|
396
|
f@0
|
397 if ( midiVal > 0 )
|
f@0
|
398 mAudioEngine.loopOn( waveIdx );
|
f@0
|
399 else
|
f@0
|
400 mAudioEngine.loopOff( waveIdx );
|
f@0
|
401 };
|
f@0
|
402 break;
|
f@0
|
403
|
f@0
|
404 case 5: // trigger record
|
f@0
|
405 mAudioEngine.record( waveIdx );
|
f@0
|
406 break;
|
f@0
|
407
|
f@0
|
408 case 2: { // duration
|
f@0
|
409 const double midiVal = m.getData_2(); // 0-127
|
f@0
|
410 const double coeff = ci::lmap<double>( midiVal, 0.0, 127, 1.0, mConfig.getMaxGrainDurationCoeff() );
|
f@0
|
411 mAudioEngine.setGrainDurationCoeff( waveIdx, coeff );
|
f@0
|
412 mWaves[waveIdx]->getSelection().setParticleSpread( float( coeff ) );
|
f@0
|
413 };
|
f@0
|
414 break;
|
f@0
|
415
|
f@0
|
416 case 7: { // filter
|
f@0
|
417 const double midiVal = m.getData_2(); // 0-127
|
f@0
|
418 const double minCutoff = mConfig.getMinFilterCutoffFreq();
|
f@0
|
419 const double maxCutoff = mConfig.getMaxFilterCutoffFreq();
|
f@0
|
420 const double cutoff = pow( maxCutoff / 200., midiVal / 127.0 ) * minCutoff;
|
f@0
|
421 mAudioEngine.setFilterCutoff( waveIdx, cutoff );
|
f@0
|
422 const float alpha = ci::lmap<double>( midiVal, 0.0f, 127.0f, 0.f, 1.f );
|
f@0
|
423 mWaves[waveIdx]->setselectionAlpha( alpha );
|
f@0
|
424 };
|
f@0
|
425 break;
|
f@0
|
426
|
f@0
|
427
|
f@0
|
428
|
f@0
|
429 }
|
f@0
|
430 }
|
f@0
|
431 }
|
f@0
|
432
|
f@0
|
433 midiMessages.clear();
|
f@0
|
434 }
|
f@0
|
435
|
f@0
|
436
|
f@0
|
437
|
f@0
|
438 CollidoscopeApp::~CollidoscopeApp()
|
f@0
|
439 {
|
f@0
|
440 for ( int chan = 0; chan < NUM_WAVES; chan++ ){
|
f@0
|
441 /* delete the array for wave messages from audio thread */
|
f@0
|
442 delete[] mRecordWaveMessageBuffers[chan];
|
f@0
|
443 }
|
f@0
|
444 }
|
f@0
|
445
|
f@6
|
446
|
f@0
|
447 CINDER_APP( CollidoscopeApp, RendererGl, [] ( App::Settings *settings) {
|
f@6
|
448
|
f@6
|
449 const std::vector< string > args = settings->getCommandLineArgs();
|
f@6
|
450
|
f@6
|
451 int width = 0;
|
f@6
|
452 int height = 0;
|
f@6
|
453
|
f@6
|
454 try {
|
f@6
|
455 if( args.size() != 3 )
|
f@6
|
456 throw std::invalid_argument("");
|
f@6
|
457
|
f@6
|
458 width = std::stoi( args[1] );
|
f@6
|
459 height = std::stoi( args[2] );
|
f@6
|
460
|
f@6
|
461 }
|
f@6
|
462 catch( std::invalid_argument & e ){
|
f@6
|
463 console() << "Error: invalid arguments" << std::endl;
|
f@18
|
464 console() << "Usage: ./CollidoscopeApp window_width window_height" << std::endl;
|
f@18
|
465 console() << "For example: ./CollidoscopeApp 1024 768 " << std::endl;
|
f@6
|
466
|
f@6
|
467 settings->setShouldQuit( true );
|
f@6
|
468 return;
|
f@6
|
469 }
|
f@6
|
470
|
f@6
|
471 settings->setWindowSize( width, height );
|
f@6
|
472 settings->setMultiTouchEnabled( false );
|
f@6
|
473 settings->disableFrameRate();
|
f@0
|
474
|
f@0
|
475 } )
|