1 // BlinkenSisters - Hunt for the Lost Pixels
2 //     Bringing back the fun of the 80s
3 //
4 // (C) 2005-07 Rene Schickbauer, Wolfgang Dautermann
5 //
6 // See License.txt for licensing information
7 //
8 
9 
10 #include "../globals.h"
11 #include "guihandler.h"
12 #include "../memops.h"
13 #include "../errorhandler.h"
14 #include "../drawprimitives.h"
15 #include "../blending.h"
16 #include "../showtext.h"
17 #include "blinkensound.h"
18 #include "../engine.h"
19 #include <stdio.h>
20 #include <string.h>
21 
22 SDL_Surface* guibg = 0;
23 SDL_Surface* buttons[5];
24 bool mouseShown = false;
25 Sint32 mouseX = 100;
26 Sint32 mouseY = 100;
27 bool buttonMouseOver[5];
28 //char* titleDisplay[] = {"Intro", "Menu", "Orient"};
29 //char* titleFile[] = {"introMusic.ogg", "menuMusic.ogg", "sisters_orient.ogg"};
30 Sint32 maxSnd = -1;
31 Sint32 curSnd = 0;
32 double scrolloffset = SCR_WIDTH / 2 * -1;
33 
34 TITLES titles[100];
35 
initGUI(char * playlist)36 void initGUI(char * playlist) {
37 
38 	char fullfname[MAX_FNAME_LENGTH];
39 	sprintf(fullfname, "%s", configGetPath("blinkenplayerbg.bmp"));
40 	SDL_Surface* temp = IMG_Load(fullfname);
41 	if(!temp) {
42 		DIE(ERROR_IMAGE_READ, fullfname);
43 	}
44 	guibg = SDL_DisplayFormat(temp);
45 	SDL_FreeSurface(temp);
46 
47 	const char* buttonfiles[] = {"player_prev.bmp",
48 	                     "player_stop.bmp",
49 	                     "player_play.bmp",
50 	                     "player_pause.bmp",
51 	                     "player_next.bmp"};
52 
53     for(Uint32 i = 0; i < 5; i++) {
54         sprintf(fullfname, "%s", configGetPath(buttonfiles[i]));
55 	    temp = IMG_Load(fullfname);
56     	 if(!temp) {
57              DIE(ERROR_IMAGE_READ, fullfname);
58          }
59 	     buttons[i] = SDL_DisplayFormat(temp);
60 	     SDL_FreeSurface(temp);
61 	     buttonMouseOver[i] = false;
62      }
63 
64     if ( playlist == NULL) {
65 	/* Play the blinkensisters sounds. No user defined playlist */
66 	FILE* fh = fopen(configGetPath("playersounds.dat"), "r");
67 	if(!fh) {
68             DIE(ERROR_FILE_READ, configGetPath("playersounds.dat"));
69 	}
70 
71 	char line[1001];
72 	char* tmpchar;
73 	char* tmpchar2;
74 	while(!feof(fh)) {
75 		maxSnd++;
76 		if(!fgets(line, 1000, fh)) {
77 			break;
78 		}
79 		while((tmpchar = strstr(line, "\n"))) {
80 			*tmpchar = 0;
81 		}
82 		while((tmpchar = strstr(line, "\r"))) {
83 			*tmpchar = 0;
84 		}
85 
86 
87 		if(!(tmpchar = strstr(line, "|"))) {
88 			DIE(ERROR_HTTPTOC, "1|2");
89 		}
90 		*tmpchar = 0;
91 		sprintf(titles[maxSnd].name, "%s", line);
92 		tmpchar++;
93 		tmpchar2 = tmpchar;
94 
95 		if(!(tmpchar = strstr(tmpchar, "|"))) {
96 			DIE(ERROR_HTTPTOC, "2|3");
97 		}
98 		*tmpchar = 0;
99 		sprintf(titles[maxSnd].fname, "%s", tmpchar2);
100 		tmpchar++;
101 		tmpchar2 = tmpchar;
102 
103 		sprintf(titles[maxSnd].scrolltext, "%s", tmpchar2);
104 		soundLoad(maxSnd, titles[maxSnd].fname);
105     	}
106     	fclose(fh);
107     } else {
108 	/* Playlist != NULL. Play the songs in the playlist */
109 	/* FIXME: Currently only Filenames, no HTTP-URLs allowed */
110 	printf("Playlsit: %s\n",playlist);
111 	FILE* fh = fopen(playlist, "r");
112 	if(!fh) {
113             DIE(ERROR_FILE_READ, playlist);
114         }
115 	char line[1001];
116 	char* tmpchar;
117 	while(!feof(fh)) {
118 		maxSnd++;
119 		if(!fgets(line, 1000, fh)) {
120 			break;
121 		}
122 		printf("line: %s\n",line);
123 		while((tmpchar = strstr(line, "\n"))) {
124 			*tmpchar = 0;
125 		}
126 		while((tmpchar = strstr(line, "\r"))) {
127 			*tmpchar = 0;
128 		}
129 
130 		printf("Zeile: %s\n",line);
131 		/* FIXME: Use Information from Ogg-tags for the scrolltest and name */
132 		sprintf(titles[maxSnd].name, "File: %d", maxSnd);
133 		sprintf(titles[maxSnd].fname, "%s", line);
134 		sprintf(titles[maxSnd].scrolltext, "Playing File number %d. Hope you like it.", maxSnd);
135 		titles[maxSnd].sdlmusic = Mix_LoadMUS(titles[maxSnd].fname);
136 		if(!titles[maxSnd].sdlmusic) {
137 			DIE(ERROR_SOUND_READ, titles[maxSnd].fname);
138 		}
139     	}
140     	fclose(fh);
141     }
142 
143 }
144 
deInitGUI()145 void deInitGUI() {
146 	SDL_FreeSurface(guibg);
147 	guibg = 0;
148 }
149 
showGUI()150 void showGUI() {
151 
152 
153 	// Lock screen
154 	if (SDL_MUSTLOCK(gScreen))
155 		if (SDL_LockSurface(gScreen) < 0)
156 			return;
157 
158 
159 	// Lock guibg
160 	if (SDL_MUSTLOCK(guibg))
161 		if (SDL_LockSurface(guibg) < 0)
162 			return;
163 
164 	Uint32 pitch_bg = gScreen->pitch / 4;
165 
166 	// Copy the background into the bigger surface
167 	Uint32 bigpitch = gScreen->pitch;
168 	Uint32 bigpitchBG = guibg->pitch;
169 
170 	long fc_src_long = (long)guibg->pixels;
171 	long fc_dst_long = (long)gScreen->pixels;
172 
173 	for(Uint32 j=0; j < SCR_HEIGHT; j++) {
174 		fc_src = (fastcopy *)fc_src_long;
175 		fc_dest = (fastcopy *)fc_dst_long;
176 		*fc_dest = *fc_src;
177 		fc_dst_long += bigpitch;
178 		fc_src_long += bigpitchBG;
179 	}
180 
181 	// Unlock guibg
182 	if (SDL_MUSTLOCK(guibg))
183 		SDL_UnlockSurface(guibg);
184 
185 
186     // Paint Buttons
187     Uint32 buttonpitch;
188     Uint32 color;
189     Uint32 width, height;
190     for(Uint32 c = 0; c < 5; c++) {
191         if(buttonMouseOver[c]) {
192             blend_darkenRect((c+1) * 40, 200, 32, 32, 0xd0b0b0);
193         } else {
194             blend_darkenRect((c+1) * 40, 200, 32, 32, 0x909090);
195         }
196     	if (SDL_MUSTLOCK(buttons[c]))
197 	 	   if (SDL_LockSurface(buttons[c]) < 0)
198 			  return;
199 
200         buttonpitch = buttons[c]->pitch / 4;
201         width = buttons[c]->w;
202         height = buttons[c]->h;
203 
204 
205     	for(Uint32 ybg = 0; ybg < height; ybg++) {
206     		for(Uint32 xbg = 0; xbg < width; xbg++) {
207     			color = ((Uint32*)buttons[c]->pixels)[xbg + ybg * buttonpitch];
208 
209     			if(color != 0x0000ff00) {
210     				((Uint32*)gScreen->pixels)[xbg + (c + 1) * 40 + (ybg + 200) * pitch_bg] = color;
211     			}
212 
213     		}
214     	}
215 
216         if (SDL_MUSTLOCK(buttons[c]))
217 	        SDL_UnlockSurface(buttons[c]);
218 
219     }
220 
221     // Paint title
222     blend_darkenRect(5, 30, 300, 25, 0x808080);
223     drawstring(10, 35, titles[curSnd].name, gScreen);
224 
225     // Paint scroller
226     blend_darkenRect(0, 0, SCR_WIDTH, 25, 0xa0a0a0);
227     drawstring((Sint32)scrolloffset * -1, 5, titles[curSnd].scrolltext, gScreen);
228 
229     // Paint status
230     blend_darkenRect(7 * 40, 200, 100, 32, 0xa0a0a0);
231     if(isPaused) {
232         drawstring(7 * 40 + 8, 208, "Paused", gScreen);
233     } else if(isPlaying) {
234         drawstring(7 * 40 + 8, 208, "Playing", gScreen);
235     } else {
236         drawstring(7 * 40 + 8, 208, "Stopped", gScreen);
237     }
238 
239     // --- Paint waveform ---
240 		// -- Background
241     blend_darkenRect(40, 50, 340, 128, 0xa0a0a0);
242 
243 		// -- Grid
244 	blend_darkenRect(40, 94, 340, 3, 0xa0a0a0);
245 	blend_darkenRect(40, 134, 340, 3, 0xa0a0a0);
246 	for(Uint32 offs = 0; offs < 340; offs += 68) {
247 		blend_darkenRect(40 + offs, 50, 3, 128, 0xa0a0a0);
248 	}
249 	blend_darkenRect(377, 50, 3, 128, 0xa0a0a0);
250 	blend_darkenRect(40, 50, 340, 3, 0xa0a0a0);
251 	blend_darkenRect(40, 175, 340, 3, 0xa0a0a0);
252 
253     Sint16 *curWav = (Sint16*)captureSound;
254     curWav++;
255     Sint16 val;
256     Sint16 lastval;
257 
258     // find next zero point
259     bool nfound = false;
260     lastval = (curWav[0] >> 9);
261     for(Uint32 offs = 0; offs < 1300; offs++) {
262         val = (curWav[0] >> 9);
263         if(val > 0 && lastval < 0) {
264                nfound = true;
265                break;
266         }
267         curWav++;
268         curWav++;
269     }
270 
271 
272     // do the painting
273     for(Uint32 offs = 0; offs < 340; offs++) {
274         val = (curWav[0] >> 9) + 50 + 44;
275         curWav++;
276         ((Uint32*)gScreen->pixels)[offs + 40 + val * pitch_bg] = 0x00ff00;
277 		((Uint32*)gScreen->pixels)[offs + 40 + (val+1) * pitch_bg] = 0x00ff00;
278 		((Uint32*)gScreen->pixels)[offs + 40 + (val+2) * pitch_bg] = 0x00ff00;
279         val = (curWav[0] >> 9) + 50 + 84;
280         curWav++;
281         ((Uint32*)gScreen->pixels)[offs + 40 + val * pitch_bg] = 0xff0000;
282 		((Uint32*)gScreen->pixels)[offs + 40 + (val+1) * pitch_bg] = 0xff0000;
283 		((Uint32*)gScreen->pixels)[offs + 40 + (val+2) * pitch_bg] = 0xff0000;
284         //curWav++;
285         //curWav++;
286     }
287 
288 	// Paint mouse cursor
289 	if(mouseShown) {
290 		// Do NOT show the crosshair cursor
291 		//drawrect(mouseX - 15, mouseY-1, 30, 3, 0x00a0a0a0);
292 		//drawrect(mouseX-1, mouseY - 15, 3, 30, 0x00a0a0a0);
293 	}
294 
295 	// Unlock Surfaces if needed
296 	if (SDL_MUSTLOCK(gScreen))
297 		SDL_UnlockSurface(gScreen);
298 
299 	// Tell SDL to update the whole screen
300 	SDL_Flip(gScreen);
301 
302 }
303 
runGUI()304 void runGUI() {
305 	SDL_Event event;
306 	Sint32 x = 0;
307 	Sint32 y = 0;
308     Sint32 i;
309     gLastTick = BS_GetTicks();
310 
311 	//SDL_ShowCursor(SDL_DISABLE);
312 	while(1) {
313 		while (SDL_PollEvent(&event))
314 		{
315 			switch (event.type)
316 			{
317 				case SDL_QUIT:
318 					//SDL_ShowCursor(SDL_ENABLE);
319 					return;
320 				case SDL_KEYUP:
321 					if (event.key.keysym.sym == SDLK_q) {
322 						//SDL_ShowCursor(SDL_ENABLE);
323 						return;
324 					}
325 				case SDL_MOUSEMOTION:
326 					x = event.motion.x;
327 					y = event.motion.y;
328 					if(!mouseShown && x > 0 && x < SCR_WIDTH - 1 && y > 0 && y < SCR_HEIGHT - 1) {
329 						mouseShown = true;
330 						SDL_WM_GrabInput(SDL_GRAB_ON);
331 					  } else if (x == 0 || x == SCR_WIDTH - 1 || y == 0 || y == SCR_HEIGHT - 1) {
332 						mouseShown = false;
333 						SDL_WM_GrabInput(SDL_GRAB_OFF);
334 					}
335 
336 					mouseX = x;
337 					mouseY = y;
338 					break;
339 
340 				case SDL_MOUSEBUTTONUP:
341                     if(event.button.button == SDL_BUTTON_LEFT) {
342                     for(i = 0; i < 5; i++) {
343                         if(mouseShown && y >= 200 && x < 232 && x >= (i+1)*40 && x < (i+1)*40+32) {
344                             switch(i) {
345                                 case 0:
346                                     soundStepPrev();
347                                     scrolloffset = SCR_WIDTH / 2 * -1;
348                                     break;
349                                 case 1:
350                                     soundStopMusic();
351                                     break;
352                                 case 2:
353                                     soundStartMusic();
354                                     break;
355                                 case 3:
356                                     soundPauseMusic();
357                                     break;
358                                 case 4:
359                                     soundStepNext();
360                                     scrolloffset = SCR_WIDTH / 2 * -1;
361                                     break;
362                             }
363                         }
364                     }
365                 }
366 			}
367 
368             //blend_darkenRect((c+1) * 40, 200, 32, 32, 0xa0a0a0);
369             for(i = 0; i < 5; i++) {
370                 if(mouseShown && y >= 200 && x < 232 && x >= (i+1)*40 && x < (i+1)*40+32) {
371                     buttonMouseOver[i] = true;
372                 } else {
373                     buttonMouseOver[i] = false;
374                 }
375             }
376 
377 		}
378 
379 
380 		// "Physics" engine
381         Uint32 tick = BS_GetTicks();
382     	// Delay a bit if we're too fast
383     	while (tick <= gLastTick) {
384     		SDL_Delay(1);
385     		//sprintf(errorMessage, "TOO FAST!");
386     		tick = BS_GetTicks();
387     	}
388 
389     	while (gLastTick < tick)
390     	{
391             // Run at virtual 100FPS
392     		gLastTick += 10;
393     		scrolloffset += 0.7;
394     		if(scrolloffset > (double)(getstringwidth(titles[curSnd].scrolltext) + SCR_WIDTH)) {
395                 scrolloffset = -SCR_WIDTH;
396             }
397         }
398 
399 		showGUI();
400 
401 	}
402 }
403 
404