summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ericson <kjell@haxx.se>2004-06-18 09:05:19 +0000
committerKjell Ericson <kjell@haxx.se>2004-06-18 09:05:19 +0000
commitfb9dbb623a40a312288beca68d3a5a466b0a2a88 (patch)
treef3814a4a2aced37cd201dc4f79b262a0afeb578b
parenta3958793e148d478ea7f1a76fcb0e0ef0e7f833b (diff)
downloadrockbox-fb9dbb623a40a312288beca68d3a5a466b0a2a88.tar.gz
rockbox-fb9dbb623a40a312288beca68d3a5a466b0a2a88.zip
First version of my chessclock. Only tried on Player. Lacking a simulator
environment made me prohibit compilation for recorders. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4769 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/chessclock.c488
1 files changed, 488 insertions, 0 deletions
diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c
new file mode 100644
index 0000000000..897f05aebb
--- /dev/null
+++ b/apps/plugins/chessclock.c
@@ -0,0 +1,488 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Kjell Ericson
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20#ifdef HAVE_LCD_CHARCELLS
21/* We only support players at a start. I don't have simulator capacity at
22 the time. */
23
24/* here is a global api struct pointer. while not strictly necessary,
25 it's nice not to have to pass the api pointer in all function calls
26 in the plugin */
27static struct plugin_api* rb;
28#define MAX_PLAYERS 10
29
30static struct {
31 int nr_timers;
32 int total_time;
33 int round_time;
34} settings;
35
36static struct {
37 int total_time;
38 int used_time;
39 bool hidden;
40} timer_holder[MAX_PLAYERS];
41
42static int run_timer(int nr);
43static int chessclock_set_int(char* string,
44 int* variable,
45 int step,
46 int min,
47 int max,
48 int flags);
49#define FLAGS_SET_INT_SECONDS 1
50
51static char * show_time(int secs);
52static int simple_menu(int nr, char **strarr);
53
54static bool pause;
55
56#define MAX_TIME 7200
57
58/* this is the plugin entry point */
59enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
60{
61 int i;
62 bool done;
63 int nr;
64
65 TEST_PLUGIN_API(api);
66
67 (void)parameter;
68 rb=api;
69
70 rb->memset(&settings, 0, sizeof(settings));
71
72 /* now go ahead and have fun! */
73 rb->splash(HZ, true, "Chess Clock");
74
75 rb->lcd_clear_display();
76 i=0;
77 while (i>=0) {
78 int res;
79 switch (i) {
80 case 0:
81 res=chessclock_set_int("Number of players",
82 &settings.nr_timers, 1, 1,
83 MAX_PLAYERS, 0);
84 break;
85 case 1:
86 res=chessclock_set_int("Total time",
87 &settings.total_time, 10, 0, MAX_TIME,
88 FLAGS_SET_INT_SECONDS);
89 settings.round_time=settings.total_time;
90 break;
91 case 2:
92 res=chessclock_set_int("Max round time", &settings.round_time,
93 10, 0, settings.round_time,
94 FLAGS_SET_INT_SECONDS);
95 break;
96 default:
97 i=-1; /* done */
98 res=-2;
99 break;
100 }
101 if (res==-1) {
102 rb->usb_screen();
103 return PLUGIN_USB_CONNECTED;
104 }
105 if (res==0) {
106 i--;
107 if (i<0) {
108 return PLUGIN_OK;
109 }
110 }
111 if (res>0) {
112 i++;
113 }
114 }
115 for (i=0; i<settings.nr_timers; i++) {
116 timer_holder[i].total_time=settings.total_time;
117 timer_holder[i].used_time=0;
118 timer_holder[i].hidden=false;
119 }
120
121 pause=true; /* We start paused */
122
123 nr=0;
124 do {
125 int ret=0;
126 done=true;
127 for (i=0; done && i<settings.nr_timers; i++) {
128 if (!timer_holder[i].hidden)
129 done=false;
130 }
131 if (done) {
132 return PLUGIN_OK;
133 }
134 if (!timer_holder[nr].hidden) {
135 done=false;
136 ret=run_timer(nr);
137 }
138 switch (ret) {
139 case -1: /* exit */
140 done=true;
141 break;
142 case 3:
143 rb->usb_screen();
144 return PLUGIN_USB_CONNECTED;
145 case 1:
146 nr++;
147 if (nr>=settings.nr_timers)
148 nr=0;
149 break;
150 case 2:
151 nr--;
152 if (nr<0)
153 nr=settings.nr_timers-1;
154 break;
155 }
156 } while (!done);
157 return PLUGIN_OK;
158}
159
160/*
161 -1= exit
162 1 = next player
163 2 = prev player
164 3 = usb connected
165*/
166static int run_timer(int nr)
167{
168 char buf[40];
169 char player_info[13];
170 long last_tick;
171 bool done=false;
172 int retval=0;
173 long max_ticks=timer_holder[nr].total_time*HZ-timer_holder[nr].used_time;
174 long ticks=0;
175 bool round_time=false;
176
177 rb->lcd_icon(ICON_PAUSE, pause);
178
179 if (settings.round_time*HZ<max_ticks) {
180 max_ticks=settings.round_time*HZ;
181 round_time=true;
182 }
183 rb->snprintf(player_info, sizeof(player_info), "Player %d", nr+1);
184 rb->lcd_puts(0, 0, player_info);
185 last_tick=*rb->current_tick;
186
187 while (!done) {
188 int button;
189 if (ticks>max_ticks) {
190 if (round_time)
191 rb->lcd_puts(0, 1, "ROUND UP!");
192 else
193 rb->lcd_puts(0, 1, "TIME OUT!");
194 rb->backlight_on();
195 } else {
196 /*
197 if (((int)(rb->current_tick - start_ticks)/HZ)&1) {
198 rb->lcd_puts(0, 0, player_info);
199 } else {
200 rb->lcd_puts(0, 0, player_info);
201 }
202 */
203 rb->lcd_puts(0, 0, player_info);
204 long now=*rb->current_tick;
205 if (!pause) {
206 ticks+=now-last_tick;
207 if ((max_ticks-ticks)/HZ == 10) {
208 /* Backlight on if 10 seconds remain */
209 rb->backlight_on();
210 }
211 }
212 last_tick=now;
213 if (round_time) {
214 rb->snprintf(buf, sizeof(buf), "%s/",
215 show_time((max_ticks-ticks+HZ-1)/HZ));
216 /* Append total time */
217 rb->strcpy(&buf[rb->strlen(buf)],
218 show_time((timer_holder[nr].total_time*HZ-
219 timer_holder[nr].used_time-
220 ticks+HZ-1)/HZ));
221 rb->lcd_puts(0, 1, buf);
222 } else {
223 rb->lcd_puts(0, 1, show_time((max_ticks-ticks+HZ-1)/HZ));
224 }
225 }
226 button = rb->button_get_w_tmo(10);
227 switch (button) {
228 /* OFF/MENU key to exit */
229#ifdef HAVE_RECORDER_KEYPAD
230 case BUTTON_OFF:
231#else
232 case BUTTON_ON:
233#endif
234 return -1; /* Indicate exit */
235
236 /* PLAY = Stop/Start toggle */
237 case BUTTON_PLAY:
238 pause=!pause;
239 rb->lcd_icon(ICON_PAUSE, pause);
240 break;
241
242 /* LEFT = Reset timer */
243 case BUTTON_STOP:
244 ticks=0;
245 break;
246
247 /* MENU */
248 case BUTTON_MENU:
249 {
250 int ret;
251 char *menu[]={"Delete player", "Restart round",
252 "Set round time", "Set total time"};
253 ret=simple_menu(4, menu);
254 if (ret==-1) {
255 retval = 3;
256 done=true;
257 } else if (ret==-2) {
258 } else if (ret==0) {
259 /* delete timer */
260 timer_holder[nr].hidden=true;
261 retval=1;
262 done=true;
263 break;
264 } else if (ret==1) {
265 /* restart */
266 ticks=0;
267 break;
268 } else if (ret==2) {
269 /* set round time */
270 int res;
271 int val=(max_ticks-ticks)/HZ;
272 res=chessclock_set_int("Round time",
273 &val,
274 10, 0, MAX_TIME,
275 FLAGS_SET_INT_SECONDS);
276 if (res==-1) { /*usb*/
277 retval = 3;
278 done=true;
279 } else if (res==1) {
280 ticks=max_ticks-val*HZ;
281 }
282 } else if (ret==3) {
283 /* set total time */
284 int res;
285 int val=timer_holder[nr].total_time;
286 res=chessclock_set_int("Total time",
287 &val,
288 10, 0, MAX_TIME,
289 FLAGS_SET_INT_SECONDS);
290 if (res==-1) { /*usb*/
291 retval = 3;
292 done=true;
293 } else if (res==1) {
294 timer_holder[nr].total_time=val;
295 }
296 }
297 }
298 break;
299
300 /* UP (RIGHT/+) = Scroll Lap timer up */
301#ifdef HAVE_RECORDER_KEYPAD
302 case BUTTON_UP:
303#else
304 case BUTTON_RIGHT:
305#endif
306 retval = 1;
307 done = true;
308 break;
309
310 /* DOWN (LEFT/-) = Scroll Lap timer down */
311#ifdef HAVE_RECORDER_KEYPAD
312 case BUTTON_DOWN:
313#else
314 case BUTTON_LEFT:
315#endif
316 retval = 2;
317 done = true;
318 break;
319
320 case SYS_USB_CONNECTED:
321 retval = 3;
322 done=true;
323 break;
324 }
325 rb->sleep(HZ/4); /* Sleep 1/4 of a second */
326 }
327
328 timer_holder[nr].used_time+=ticks;
329
330 return retval;
331}
332
333static int chessclock_set_int(char* string,
334 int* variable,
335 int step,
336 int min,
337 int max,
338 int flags)
339{
340 bool done = false;
341 int button;
342
343#ifdef HAVE_LCD_BITMAP
344 if(global_settings.statusbar)
345 rb->lcd_setmargins(0, STATUSBAR_HEIGHT);
346 else
347 rb->lcd_setmargins(0, 0);
348#endif
349
350 rb->lcd_clear_display();
351 rb->lcd_puts_scroll(0, 0, string);
352
353 while (!done) {
354 char str[32];
355 if (flags & FLAGS_SET_INT_SECONDS)
356 rb->snprintf(str, sizeof str,"%s (m:s)", show_time(*variable));
357 else
358 rb->snprintf(str, sizeof str,"%d", *variable);
359 rb->lcd_puts(0, 1, str);
360#ifdef HAVE_LCD_BITMAP
361 rb->status_draw(true);
362 rb->lcd_update();
363#endif
364 button = rb->button_get_w_tmo(HZ/2);
365 switch(button) {
366#ifdef HAVE_RECORDER_KEYPAD
367 case BUTTON_UP:
368 case BUTTON_UP | BUTTON_REPEAT:
369#else
370 case BUTTON_RIGHT:
371 case BUTTON_RIGHT | BUTTON_REPEAT:
372#endif
373 *variable += step;
374 break;
375
376#ifdef HAVE_RECORDER_KEYPAD
377 case BUTTON_DOWN:
378 case BUTTON_DOWN | BUTTON_REPEAT:
379#else
380 case BUTTON_LEFT:
381 case BUTTON_LEFT | BUTTON_REPEAT:
382#endif
383 *variable -= step;
384 break;
385
386#ifdef HAVE_RECORDER_KEYPAD
387 case BUTTON_LEFT:
388 case BUTTON_PLAY:
389#else
390 case BUTTON_PLAY:
391#endif
392 done = true;
393 break;
394
395#ifdef HAVE_RECORDER_KEYPAD
396 case BUTTON_OFF:
397#else
398 case BUTTON_STOP:
399 case BUTTON_MENU:
400#endif
401 return 0; /* cancel */
402 break;
403
404 case SYS_USB_CONNECTED:
405 return -1;
406
407 }
408 if(*variable > max )
409 *variable = max;
410
411 if(*variable < min )
412 *variable = min;
413
414 }
415 rb->lcd_stop_scroll();
416
417 return 1;
418}
419
420static char * show_time(int seconds)
421{
422 static char buf[]="00:00";
423 rb->snprintf(buf, sizeof(buf), "%02d:%02d", seconds/60, seconds%60);
424 return buf;
425}
426
427/* -1 = USB
428 -2 = cancel
429*/
430static int simple_menu(int nr, char **strarr)
431{
432 int show=0;
433 int button;
434 rb->lcd_clear_display();
435
436 while (1) {
437 if (show>=nr)
438 show=0;
439 if (show<0)
440 show=nr-1;
441 rb->lcd_puts_scroll(0, 0, strarr[show]);
442 button = rb->button_get(false);
443 switch(button) {
444#ifdef HAVE_RECORDER_KEYPAD
445 case BUTTON_UP:
446 case BUTTON_UP | BUTTON_REPEAT:
447#else
448 case BUTTON_RIGHT:
449 case BUTTON_RIGHT | BUTTON_REPEAT:
450#endif
451 show++;
452 break;
453
454#ifdef HAVE_RECORDER_KEYPAD
455 case BUTTON_DOWN:
456 case BUTTON_DOWN | BUTTON_REPEAT:
457#else
458 case BUTTON_LEFT:
459 case BUTTON_LEFT | BUTTON_REPEAT:
460#endif
461 show--;
462 break;
463
464#ifdef HAVE_RECORDER_KEYPAD
465 case BUTTON_LEFT:
466 case BUTTON_PLAY:
467#else
468 case BUTTON_PLAY:
469#endif
470 return show;
471 break;
472
473#ifdef HAVE_RECORDER_KEYPAD
474 case BUTTON_OFF:
475#else
476 case BUTTON_STOP:
477 case BUTTON_MENU:
478#endif
479 return -2; /* cancel */
480 break;
481
482 case SYS_USB_CONNECTED:
483 return -1;
484 }
485 }
486}
487
488#endif /* HAVE_LCD_CHARCELLS */