1 /*
2  * Author: Harry van Haaren 2013
3  *         harryhaaren@gmail.com
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "gridlogic.hxx"
20 
21 #include "jack.hxx"
22 
23 #include "trackoutput.hxx"
24 #include "controllerupdater.hxx"
25 
26 extern Jack* jack;
27 
28 const char* GridLogic::StateString[8] = {
29 	"Empty",
30 	"Playing",
31 	"Play queued",
32 	"Stopped",
33 	"Stop queued",
34 	"Recording",
35 	"Record queued"
36 };
37 
GridLogic()38 GridLogic::GridLogic()
39 {
40 	sceneLaunch = 0;
41 
42 	sampleTrackScene = false;
43 	selectedTrack = 0;
44 	selectedScene = 0;
45 }
46 
selectedTrackSceneEvent(bool p)47 void GridLogic::selectedTrackSceneEvent(bool p)
48 {
49 	if ( p ) {
50 		pressed( selectedTrack, selectedScene );
51 	} else {
52 		released( selectedTrack, selectedScene );
53 	}
54 }
55 
setSelectTrackScene(bool b)56 void GridLogic::setSelectTrackScene(bool b)
57 {
58 	char tmp[40];
59 	sprintf( tmp, "Select track enable %i", int(b) );
60 	EventGuiPrint e( tmp );
61 	writeToGuiRingbuffer( &e );
62 	sampleTrackScene = b;
63 }
64 
getLaunchedScene()65 int GridLogic::getLaunchedScene()
66 {
67 	return sceneLaunch;
68 }
69 
getSelectedTrack()70 int GridLogic::getSelectedTrack()
71 {
72 	return selectedTrack;
73 }
74 
getSelectedScene()75 int GridLogic::getSelectedScene()
76 {
77 	return selectedScene;
78 }
79 
setSelectedTrack(int t)80 void GridLogic::setSelectedTrack(int t)
81 {
82 	selectedTrack = t;
83 }
84 
setSelectedScene(int s)85 void GridLogic::setSelectedScene(int s)
86 {
87 	selectedScene = s;
88 }
89 
90 
launchScene(int scene)91 void GridLogic::launchScene( int scene )
92 {
93 	for(unsigned int t = 0; t < NTRACKS; t++ ) {
94 		for(int s = 0; s < NSCENES; s++ ) {
95 			LooperClip* lc = jack->getLooper( t )->getClip( s );
96 			if ( s == scene ) {
97 				lc->queuePlay();
98 				jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
99 			} else {
100 				if ( lc->playing() ) {
101 					lc->queueStop();
102 					jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
103 				} else if ( lc->somethingQueued() ) {
104 					lc->neutralize();
105 					jack->getControllerUpdater()->setSceneState( t, s, lc->getState() );
106 				}
107 			}
108 		}
109 	}
110 
111 	sceneLaunch = scene;
112 
113 	jack->getControllerUpdater()->launchScene( scene );
114 }
115 
specialScene(int t,int s)116 void GridLogic::specialScene(int t, int s)
117 {
118 	if ( t < 0 ) t = 0;
119 	if ( t >= NTRACKS ) t = NTRACKS-1;
120 
121 	if ( s < 0 ) s = 0;
122 	if ( s >= NSCENES ) s = NSCENES-1;
123 
124 	selectedTrack = t;
125 	selectedScene = s;
126 
127 	// update UI's
128 	jack->getControllerUpdater()->specialScene( t, s );
129 }
130 
pressed(int track,int scene)131 void GridLogic::pressed( int track, int scene )
132 {
133 	if ( sampleTrackScene ) {
134 		specialScene( track, scene );
135 
136 		// don't act on grid press!
137 		return;
138 	}
139 
140 
141 	// get the clip, do the "press" action based on current state.
142 	LooperClip* lc  = jack->getLooper( track )->getClip( scene );
143 	TrackOutput* to = jack->getTrackOutput( track );
144 	GridLogic::State s = lc->getState();
145 
146 #ifdef DEBUG_CLIP
147 	printf("GridLogic::pressed() before press state = %s\n", StateString[ int(scene) ] );
148 #endif
149 
150 	if ( to->recordArm() && !lc->recording() ) {
151 		lc->queueRecord();
152 		to->recordArm(false);
153 		jack->getControllerUpdater()->recordArm( track, false );
154 	} else {
155 		if ( s == STATE_EMPTY )
156 			lc->queueRecord();
157 
158 		if ( s == STATE_STOPPED ) {
159 			// hack, stop all scenes, then launch proper one
160 			for( int i = 0; i < NTRACKS; i++ ) {
161 				LooperClip* ilc = jack->getLooper( track )->getClip( i );
162 				if ( ilc->playing() ) {
163 					ilc->queueStop();
164 				}
165 			}
166 
167 			lc->queuePlay();
168 		}
169 
170 		if ( s == STATE_PLAYING )
171 			lc->queueStop();
172 
173 		if ( s == STATE_RECORDING )
174 			lc->queuePlay();
175 
176 		if ( s == STATE_PLAY_QUEUED )
177 			lc->queueStop();
178 
179 		if ( s == STATE_STOP_QUEUED )
180 			lc->queuePlay();
181 
182 		// don't re-trigger if already playing!
183 		if ( s == STATE_STOP_QUEUED && lc->playing() )
184 			lc->neutralize();
185 
186 		if ( s == STATE_RECORD_QUEUED )
187 			lc->neutralize();
188 	}
189 
190 	// check state of new clip, if getQueuePlay() == true, queueStop() all other scenes
191 	//if ( lc->getQueuePlay() )
192 	{
193 		for(int i = 0; i < NSCENES; i++) {
194 			// exclude current scene
195 			if ( i != scene ) {
196 				//LUPPP_NOTE("netralizing & qStop on scene %i due to press on %i", i, scene );
197 				LooperClip* ilc = jack->getLooper( track )->getClip( i );
198 
199 				ilc->neutralize();
200 				ilc->queueStop();
201 				jack->getControllerUpdater()->setSceneState(track, i, ilc->getState() );
202 			}
203 		}
204 	}
205 
206 
207 	s = lc->getState();
208 #ifdef DEBUG_CLIP
209 	printf("GridLogic::pressed() after press state = %s\n", StateString[ int(s) ] );
210 #endif
211 	jack->getControllerUpdater()->setSceneState(track, scene, s );
212 }
213 
clear(int track,int scene)214 void GridLogic::clear( int track, int scene )
215 {
216 	jack->getLooper( track )->getClip( scene )->init();
217 	jack->getControllerUpdater()->setTrackSceneProgress(track, scene, 0 );
218 	jack->getControllerUpdater()->setSceneState( track, scene, GridLogic::STATE_EMPTY );
219 }
220 
released(int track,int scene)221 void GridLogic::released( int track, int scene )
222 {
223 	GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
224 	jack->getControllerUpdater()->setSceneState(track, scene, s );
225 }
226 
load(int track,int scene,AudioBuffer * ab)227 void GridLogic::load(int track, int scene, AudioBuffer* ab)
228 {
229 	jack->getLooper( track )->getClip( scene )->load( ab );
230 	GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
231 	jack->getControllerUpdater()->setSceneState(track, scene, s );
232 }
233 
234 
updateState()235 void GridLogic::updateState()
236 {
237 	//printf("GridLogic::updateState() stub" );
238 	for(int t = 0; t < NTRACKS; t++) {
239 		for(int s = 0; s < NSCENES; s++) {
240 			GridLogic::State st = jack->getLooper( t )->getClip( s )->getState();
241 			EventGuiPrint e( GridLogic::StateString[st] );
242 			writeToGuiRingbuffer( &e );
243 			jack->getControllerUpdater()->setSceneState(t, s, st );
244 		}
245 	}
246 }
247 
bar()248 void GridLogic::bar()
249 {
250 #ifdef DEBUG_CLIP
251 	EventGuiPrint e( "GridLogic::bar()" );
252 	//writeToGuiRingbuffer( &e );
253 #endif
254 
255 	/// iterate over all clips, if they're set to QUEUED, set to the next state
256 	for( int i = 0; i < NTRACKS*NSCENES; i++ ) {
257 		int track = i / NSCENES;
258 		int scene = i - track * NSCENES;
259 		jack->getLooper( track )->getClip(scene)->bar();
260 
261 #ifdef DEBUG_CLIP
262 		GridLogic::State s = jack->getLooper( track )->getClip( scene )->getState();
263 		if ( s != STATE_EMPTY ) {
264 			//printf("%i, %i:after bar() state = %s\n", track, scene, StateString[ int(s) ] );
265 		}
266 #endif
267 	}
268 }
269 
270 
beat()271 void GridLogic::beat()
272 {
273 
274 
275 }
276 
277