Updated our source code header to explicitly mention that we are GPL v2 or
[Rockbox.git] / apps / plugins / stopwatch.c
blob2a5f97f93da7a2326f6acf01a145f1736e393d6b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Mike Holden
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
24 PLUGIN_HEADER
26 #ifdef HAVE_LCD_BITMAP
27 #define TIMER_Y 1
28 #else
29 #define TIMER_Y 0
30 #endif
32 #define LAP_Y TIMER_Y+1
33 #define MAX_LAPS 64
35 /* variable button definitions */
36 #if CONFIG_KEYPAD == RECORDER_PAD
37 #define STOPWATCH_QUIT BUTTON_OFF
38 #define STOPWATCH_START_STOP BUTTON_PLAY
39 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
40 #define STOPWATCH_LAP_TIMER BUTTON_ON
41 #define STOPWATCH_SCROLL_UP BUTTON_UP
42 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
43 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
44 #define STOPWATCH_QUIT BUTTON_OFF
45 #define STOPWATCH_START_STOP BUTTON_SELECT
46 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
47 #define STOPWATCH_LAP_TIMER BUTTON_ON
48 #define STOPWATCH_SCROLL_UP BUTTON_UP
49 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
50 #elif CONFIG_KEYPAD == ONDIO_PAD
51 #define STOPWATCH_QUIT BUTTON_OFF
52 #define STOPWATCH_START_STOP BUTTON_RIGHT
53 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
54 #define STOPWATCH_LAP_TIMER BUTTON_MENU
55 #define STOPWATCH_SCROLL_UP BUTTON_UP
56 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
57 #elif CONFIG_KEYPAD == PLAYER_PAD
58 #define STOPWATCH_QUIT BUTTON_MENU
59 #define STOPWATCH_START_STOP BUTTON_PLAY
60 #define STOPWATCH_RESET_TIMER BUTTON_STOP
61 #define STOPWATCH_LAP_TIMER BUTTON_ON
62 #define STOPWATCH_SCROLL_UP BUTTON_RIGHT
63 #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
64 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
65 (CONFIG_KEYPAD == IRIVER_H300_PAD)
66 #define STOPWATCH_QUIT BUTTON_OFF
67 #define STOPWATCH_START_STOP BUTTON_SELECT
68 #define STOPWATCH_RESET_TIMER BUTTON_DOWN
69 #define STOPWATCH_LAP_TIMER BUTTON_ON
70 #define STOPWATCH_SCROLL_UP BUTTON_RIGHT
71 #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
73 #define STOPWATCH_RC_QUIT BUTTON_RC_STOP
75 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
76 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
77 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
78 #define STOPWATCH_QUIT BUTTON_MENU
79 #define STOPWATCH_START_STOP BUTTON_SELECT
80 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
81 #define STOPWATCH_LAP_TIMER BUTTON_RIGHT
82 #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD
83 #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK
84 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
85 #define STOPWATCH_QUIT BUTTON_PLAY
86 #define STOPWATCH_START_STOP BUTTON_MODE
87 #define STOPWATCH_RESET_TIMER BUTTON_EQ
88 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
89 #define STOPWATCH_SCROLL_UP BUTTON_UP
90 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
91 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
92 #define STOPWATCH_QUIT BUTTON_POWER
93 #define STOPWATCH_START_STOP BUTTON_PLAY
94 #define STOPWATCH_RESET_TIMER BUTTON_REC
95 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
96 #define STOPWATCH_SCROLL_UP BUTTON_UP
97 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
98 #elif CONFIG_KEYPAD == GIGABEAT_PAD
99 #define STOPWATCH_QUIT BUTTON_POWER
100 #define STOPWATCH_START_STOP BUTTON_SELECT
101 #define STOPWATCH_RESET_TIMER BUTTON_A
102 #define STOPWATCH_LAP_TIMER BUTTON_MENU
103 #define STOPWATCH_SCROLL_UP BUTTON_UP
104 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
105 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
106 (CONFIG_KEYPAD == SANSA_C200_PAD)
107 #define STOPWATCH_QUIT BUTTON_POWER
108 #define STOPWATCH_START_STOP BUTTON_RIGHT
109 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
110 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
111 #define STOPWATCH_SCROLL_UP BUTTON_UP
112 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
113 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
114 #define STOPWATCH_QUIT BUTTON_POWER
115 #define STOPWATCH_START_STOP BUTTON_PLAY
116 #define STOPWATCH_RESET_TIMER BUTTON_REW
117 #define STOPWATCH_LAP_TIMER BUTTON_FF
118 #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_UP
119 #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_DOWN
120 #elif CONFIG_KEYPAD == MROBE500_PAD
121 #define STOPWATCH_QUIT BUTTON_POWER
122 #define STOPWATCH_START_STOP BUTTON_RC_HEART
123 #define STOPWATCH_RESET_TIMER BUTTON_RC_MODE
124 #define STOPWATCH_LAP_TIMER BUTTON_RC_PLAY
125 #define STOPWATCH_SCROLL_UP BUTTON_RIGHT
126 #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
127 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
128 #define STOPWATCH_QUIT BUTTON_BACK
129 #define STOPWATCH_START_STOP BUTTON_PLAY
130 #define STOPWATCH_RESET_TIMER BUTTON_MENU
131 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
132 #define STOPWATCH_SCROLL_UP BUTTON_UP
133 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
134 #elif CONFIG_KEYPAD == MROBE100_PAD
135 #define STOPWATCH_QUIT BUTTON_POWER
136 #define STOPWATCH_START_STOP BUTTON_SELECT
137 #define STOPWATCH_RESET_TIMER BUTTON_DISPLAY
138 #define STOPWATCH_LAP_TIMER BUTTON_MENU
139 #define STOPWATCH_SCROLL_UP BUTTON_UP
140 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
141 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
142 #define STOPWATCH_QUIT BUTTON_RC_REC
143 #define STOPWATCH_START_STOP BUTTON_RC_PLAY
144 #define STOPWATCH_RESET_TIMER BUTTON_RC_REW
145 #define STOPWATCH_LAP_TIMER BUTTON_RC_FF
146 #define STOPWATCH_SCROLL_UP BUTTON_RC_VOL_UP
147 #define STOPWATCH_SCROLL_DOWN BUTTON_RC_VOL_DOWN
148 #define STOPWATCH_RC_QUIT BUTTON_REC
149 #elif CONFIG_KEYPAD == COWOND2_PAD
150 #define STOPWATCH_QUIT BUTTON_POWER
151 #else
152 #error No keymap defined!
153 #endif
155 #ifdef HAVE_TOUCHPAD
156 #ifndef STOPWATCH_QUIT
157 #define STOPWATCH_QUIT BUTTON_TOPLEFT
158 #endif
159 #ifndef STOPWATCH_START_STOP
160 #define STOPWATCH_START_STOP BUTTON_CENTER
161 #endif
162 #ifndef STOPWATCH_RESET_TIMER
163 #define STOPWATCH_RESET_TIMER BUTTON_MIDRIGHT
164 #endif
165 #ifndef STOPWATCH_LAP_TIMER
166 #define STOPWATCH_LAP_TIMER BUTTON_MIDLEFT
167 #endif
168 #ifndef STOPWATCH_SCROLL_UP
169 #define STOPWATCH_SCROLL_UP BUTTON_TOPMIDDLE
170 #endif
171 #ifndef STOPWATCH_SCROLL_DOWN
172 #define STOPWATCH_SCROLL_DOWN BUTTON_BOTTOMMIDDLE
173 #endif
174 #endif
176 static const struct plugin_api* rb;
178 static int stopwatch = 0;
179 static long start_at = 0;
180 static int prev_total = 0;
181 static bool counting = false;
182 static int curr_lap = 0;
183 static int lap_scroll = 0;
184 static int lap_start;
185 static int lap_times[MAX_LAPS];
187 static void ticks_to_string(int ticks,int lap,int buflen, char * buf)
189 int hours, minutes, seconds, cs;
191 hours = ticks / (HZ * 3600);
192 ticks -= (HZ * hours * 3600);
193 minutes = ticks / (HZ * 60);
194 ticks -= (HZ * minutes * 60);
195 seconds = ticks / HZ;
196 ticks -= (HZ * seconds);
197 cs = ticks;
198 if (!lap)
200 rb->snprintf(buf, buflen,
201 "%2d:%02d:%02d.%02d",
202 hours, minutes, seconds, cs);
204 else
207 if (lap > 1)
209 int last_ticks, last_hours, last_minutes, last_seconds, last_cs;
210 last_ticks = lap_times[(lap-1)%MAX_LAPS] - lap_times[(lap-2)%MAX_LAPS];
211 last_hours = last_ticks / (HZ * 3600);
212 last_ticks -= (HZ * last_hours * 3600);
213 last_minutes = last_ticks / (HZ * 60);
214 last_ticks -= (HZ * last_minutes * 60);
215 last_seconds = last_ticks / HZ;
216 last_ticks -= (HZ * last_seconds);
217 last_cs = last_ticks;
219 rb->snprintf(buf, buflen,
220 "%2d %2d:%02d:%02d.%02d [%2d:%02d:%02d.%02d]",
221 lap, hours, minutes, seconds, cs, last_hours,
222 last_minutes, last_seconds, last_cs);
224 else
226 rb->snprintf(buf, buflen,
227 "%2d %2d:%02d:%02d.%02d",
228 lap, hours, minutes, seconds, cs);
233 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
235 char buf[32];
236 int button;
237 int lap;
238 int done = false;
239 bool update_lap = true;
240 int lines;
242 (void)parameter;
243 rb = api;
245 #ifdef HAVE_LCD_BITMAP
246 int h;
247 rb->lcd_setfont(FONT_UI);
248 rb->lcd_getstringsize("M", NULL, &h);
249 lines = (LCD_HEIGHT / h) - (LAP_Y);
250 #else
251 lines = 1;
252 #endif
254 rb->lcd_clear_display();
256 while (!done)
258 if (counting)
260 stopwatch = prev_total + *rb->current_tick - start_at;
262 else
264 stopwatch = prev_total;
267 ticks_to_string(stopwatch,0,32,buf);
268 rb->lcd_puts(0, TIMER_Y, buf);
270 if(update_lap)
272 lap_start = curr_lap - lap_scroll;
273 for (lap = lap_start; lap > lap_start - lines; lap--)
275 if (lap > 0)
277 ticks_to_string(lap_times[(lap-1)%MAX_LAPS],lap,32,buf);
278 rb->lcd_puts_scroll(0, LAP_Y + lap_start - lap, buf);
280 else
282 rb->lcd_puts(0, LAP_Y + lap_start - lap,
283 " ");
286 update_lap = false;
289 rb->lcd_update();
291 if (! counting)
293 button = rb->button_get(true);
295 else
297 button = rb->button_get_w_tmo(10);
299 /* Make sure that the jukebox isn't powered off
300 automatically */
301 rb->reset_poweroff_timer();
303 switch (button)
306 /* exit */
307 #ifdef STOPWATCH_RC_QUIT
308 case STOPWATCH_RC_QUIT:
309 #endif
310 case STOPWATCH_QUIT:
311 done = true;
312 break;
314 /* Stop/Start toggle */
315 case STOPWATCH_START_STOP:
316 counting = ! counting;
317 if (counting)
319 start_at = *rb->current_tick;
320 stopwatch = prev_total + *rb->current_tick - start_at;
322 else
324 prev_total += *rb->current_tick - start_at;
325 stopwatch = prev_total;
327 break;
329 /* Reset timer */
330 case STOPWATCH_RESET_TIMER:
331 if (!counting)
333 prev_total = 0;
334 curr_lap = 0;
335 update_lap = true;
337 break;
339 /* Lap timer */
340 case STOPWATCH_LAP_TIMER:
341 lap_times[curr_lap%MAX_LAPS] = stopwatch;
342 curr_lap++;
343 update_lap = true;
344 break;
346 /* Scroll Lap timer up */
347 case STOPWATCH_SCROLL_UP:
348 if (lap_scroll > 0)
350 lap_scroll --;
351 update_lap = true;
353 break;
355 /* Scroll Lap timer down */
356 case STOPWATCH_SCROLL_DOWN:
357 if ((lap_scroll < curr_lap - lines) &&
358 (lap_scroll < (MAX_LAPS - lines)) )
360 lap_scroll ++;
361 update_lap = true;
363 break;
365 default:
366 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
367 return PLUGIN_USB_CONNECTED;
368 break;
371 return PLUGIN_OK;