1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
26 #ifdef HAVE_LCD_BITMAP
32 #define LAP_Y TIMER_Y+1
35 #define STOPWATCH_FILE PLUGIN_APPS_DATA_DIR "/stopwatch.dat"
37 /* variable button definitions */
38 #if CONFIG_KEYPAD == RECORDER_PAD
39 #define STOPWATCH_QUIT BUTTON_OFF
40 #define STOPWATCH_START_STOP BUTTON_PLAY
41 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
42 #define STOPWATCH_LAP_TIMER BUTTON_ON
43 #define STOPWATCH_SCROLL_UP BUTTON_UP
44 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
46 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
47 #define STOPWATCH_QUIT BUTTON_OFF
48 #define STOPWATCH_START_STOP BUTTON_SELECT
49 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
50 #define STOPWATCH_LAP_TIMER BUTTON_ON
51 #define STOPWATCH_SCROLL_UP BUTTON_UP
52 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
54 #elif CONFIG_KEYPAD == ONDIO_PAD
55 #define STOPWATCH_QUIT BUTTON_OFF
56 #define STOPWATCH_START_STOP BUTTON_RIGHT
57 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
58 #define STOPWATCH_LAP_TIMER BUTTON_MENU
59 #define STOPWATCH_SCROLL_UP BUTTON_UP
60 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
62 #elif CONFIG_KEYPAD == PLAYER_PAD
63 #define STOPWATCH_QUIT BUTTON_MENU
64 #define STOPWATCH_START_STOP BUTTON_PLAY
65 #define STOPWATCH_RESET_TIMER BUTTON_STOP
66 #define STOPWATCH_LAP_TIMER BUTTON_ON
67 #define STOPWATCH_SCROLL_UP BUTTON_RIGHT
68 #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
70 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
71 (CONFIG_KEYPAD == IRIVER_H300_PAD)
72 #define STOPWATCH_QUIT BUTTON_OFF
73 #define STOPWATCH_START_STOP BUTTON_SELECT
74 #define STOPWATCH_RESET_TIMER BUTTON_DOWN
75 #define STOPWATCH_LAP_TIMER BUTTON_ON
76 #define STOPWATCH_SCROLL_UP BUTTON_RIGHT
77 #define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
78 #define STOPWATCH_RC_QUIT BUTTON_RC_STOP
80 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
81 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
82 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
83 #define STOPWATCH_QUIT BUTTON_MENU
84 #define STOPWATCH_START_STOP BUTTON_SELECT
85 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
86 #define STOPWATCH_LAP_TIMER BUTTON_RIGHT
87 #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD
88 #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK
90 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
91 #define STOPWATCH_QUIT BUTTON_PLAY
92 #define STOPWATCH_START_STOP BUTTON_MODE
93 #define STOPWATCH_RESET_TIMER BUTTON_EQ
94 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
95 #define STOPWATCH_SCROLL_UP BUTTON_UP
96 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
98 #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
99 #define STOPWATCH_QUIT BUTTON_POWER
100 #define STOPWATCH_START_STOP BUTTON_PLAY
101 #define STOPWATCH_RESET_TIMER BUTTON_REC
102 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
103 #define STOPWATCH_SCROLL_UP BUTTON_UP
104 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
106 #elif CONFIG_KEYPAD == GIGABEAT_PAD
107 #define STOPWATCH_QUIT BUTTON_POWER
108 #define STOPWATCH_START_STOP BUTTON_SELECT
109 #define STOPWATCH_RESET_TIMER BUTTON_A
110 #define STOPWATCH_LAP_TIMER BUTTON_MENU
111 #define STOPWATCH_SCROLL_UP BUTTON_UP
112 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
114 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
115 (CONFIG_KEYPAD == SANSA_C200_PAD) || \
116 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
117 (CONFIG_KEYPAD == SANSA_M200_PAD)
118 #define STOPWATCH_QUIT BUTTON_POWER
119 #define STOPWATCH_START_STOP BUTTON_RIGHT
120 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
121 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
122 #define STOPWATCH_SCROLL_UP BUTTON_UP
123 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
125 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
126 #define STOPWATCH_QUIT (BUTTON_HOME|BUTTON_REPEAT)
127 #define STOPWATCH_START_STOP BUTTON_RIGHT
128 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
129 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
130 #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_BACK
131 #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_FWD
133 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
134 #define STOPWATCH_QUIT BUTTON_POWER
135 #define STOPWATCH_START_STOP BUTTON_PLAY
136 #define STOPWATCH_RESET_TIMER BUTTON_REW
137 #define STOPWATCH_LAP_TIMER BUTTON_FF
138 #define STOPWATCH_SCROLL_UP BUTTON_SCROLL_UP
139 #define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_DOWN
141 #elif CONFIG_KEYPAD == MROBE500_PAD
142 #define STOPWATCH_QUIT BUTTON_POWER
144 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
145 #define STOPWATCH_QUIT BUTTON_BACK
146 #define STOPWATCH_START_STOP BUTTON_PLAY
147 #define STOPWATCH_RESET_TIMER BUTTON_MENU
148 #define STOPWATCH_LAP_TIMER BUTTON_SELECT
149 #define STOPWATCH_SCROLL_UP BUTTON_UP
150 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
152 #elif CONFIG_KEYPAD == MROBE100_PAD
153 #define STOPWATCH_QUIT BUTTON_POWER
154 #define STOPWATCH_START_STOP BUTTON_SELECT
155 #define STOPWATCH_RESET_TIMER BUTTON_DISPLAY
156 #define STOPWATCH_LAP_TIMER BUTTON_MENU
157 #define STOPWATCH_SCROLL_UP BUTTON_UP
158 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
160 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
161 #define STOPWATCH_QUIT BUTTON_RC_REC
162 #define STOPWATCH_START_STOP BUTTON_RC_PLAY
163 #define STOPWATCH_RESET_TIMER BUTTON_RC_REW
164 #define STOPWATCH_LAP_TIMER BUTTON_RC_FF
165 #define STOPWATCH_SCROLL_UP BUTTON_RC_VOL_UP
166 #define STOPWATCH_SCROLL_DOWN BUTTON_RC_VOL_DOWN
167 #define STOPWATCH_RC_QUIT BUTTON_REC
169 #elif CONFIG_KEYPAD == COWON_D2_PAD
170 #define STOPWATCH_QUIT BUTTON_POWER
172 #elif CONFIG_KEYPAD == IAUDIO67_PAD
173 #define STOPWATCH_QUIT BUTTON_MENU
174 #define STOPWATCH_START_STOP BUTTON_PLAY
175 #define STOPWATCH_RESET_TIMER BUTTON_STOP
176 #define STOPWATCH_LAP_TIMER BUTTON_LEFT
177 #define STOPWATCH_SCROLL_UP BUTTON_VOLUP
178 #define STOPWATCH_SCROLL_DOWN BUTTON_VOLDOWN
179 #define STOPWATCH_RC_QUIT BUTTON_POWER
181 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
182 #define STOPWATCH_QUIT BUTTON_BACK
183 #define STOPWATCH_START_STOP BUTTON_PLAY
184 #define STOPWATCH_RESET_TIMER BUTTON_SELECT
185 #define STOPWATCH_LAP_TIMER BUTTON_CUSTOM
186 #define STOPWATCH_SCROLL_UP BUTTON_UP
187 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
189 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
190 #define STOPWATCH_QUIT BUTTON_POWER
191 #define STOPWATCH_START_STOP BUTTON_SELECT
192 #define STOPWATCH_RESET_TIMER BUTTON_MENU
193 #define STOPWATCH_LAP_TIMER BUTTON_VIEW
194 #define STOPWATCH_SCROLL_UP BUTTON_UP
195 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
197 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
198 #define STOPWATCH_QUIT BUTTON_POWER
199 #define STOPWATCH_START_STOP BUTTON_PLAY
200 #define STOPWATCH_RESET_TIMER BUTTON_MENU
201 #define STOPWATCH_LAP_TIMER BUTTON_NEXT
202 #define STOPWATCH_SCROLL_UP BUTTON_UP
203 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
205 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
206 #define STOPWATCH_QUIT BUTTON_POWER
207 #define STOPWATCH_START_STOP BUTTON_PLAY
208 #define STOPWATCH_RESET_TIMER BUTTON_MENU
209 #define STOPWATCH_LAP_TIMER BUTTON_RIGHT
210 #define STOPWATCH_SCROLL_UP BUTTON_UP
211 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
213 #elif CONFIG_KEYPAD == ONDAVX747_PAD
214 #define STOPWATCH_QUIT BUTTON_POWER
215 #elif CONFIG_KEYPAD == ONDAVX777_PAD
216 #define STOPWATCH_QUIT BUTTON_POWER
218 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
219 #define STOPWATCH_QUIT BUTTON_REC
220 #define STOPWATCH_START_STOP BUTTON_PLAY
221 #define STOPWATCH_RESET_TIMER BUTTON_LEFT
222 #define STOPWATCH_LAP_TIMER BUTTON_RIGHT
223 #define STOPWATCH_SCROLL_UP BUTTON_UP
224 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
226 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
227 #define STOPWATCH_QUIT BUTTON_REC
228 #define STOPWATCH_START_STOP BUTTON_PLAY
229 #define STOPWATCH_RESET_TIMER BUTTON_OK
230 #define STOPWATCH_LAP_TIMER BUTTON_MENU
231 #define STOPWATCH_SCROLL_UP BUTTON_UP
232 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
234 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
235 #define STOPWATCH_QUIT (BUTTON_REC|BUTTON_PLAY)
236 #define STOPWATCH_START_STOP BUTTON_PLAY
237 #define STOPWATCH_RESET_TIMER BUTTON_REW
238 #define STOPWATCH_LAP_TIMER BUTTON_FF
239 #define STOPWATCH_SCROLL_UP BUTTON_VOL_UP
240 #define STOPWATCH_SCROLL_DOWN BUTTON_VOL_DOWN
242 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
243 #define STOPWATCH_QUIT (BUTTON_REC|BUTTON_REPEAT)
244 #define STOPWATCH_START_STOP BUTTON_PLAY
245 #define STOPWATCH_RESET_TIMER BUTTON_REW
246 #define STOPWATCH_LAP_TIMER BUTTON_FF
247 #define STOPWATCH_SCROLL_UP BUTTON_UP
248 #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
251 #error No keymap defined!
254 #ifdef HAVE_TOUCHSCREEN
255 #ifndef STOPWATCH_QUIT
256 #define STOPWATCH_QUIT BUTTON_TOPLEFT
258 #ifndef STOPWATCH_START_STOP
259 #define STOPWATCH_START_STOP BUTTON_CENTER
261 #ifndef STOPWATCH_RESET_TIMER
262 #define STOPWATCH_RESET_TIMER BUTTON_MIDRIGHT
264 #ifndef STOPWATCH_LAP_TIMER
265 #define STOPWATCH_LAP_TIMER BUTTON_MIDLEFT
267 #ifndef STOPWATCH_SCROLL_UP
268 #define STOPWATCH_SCROLL_UP BUTTON_TOPMIDDLE
270 #ifndef STOPWATCH_SCROLL_DOWN
271 #define STOPWATCH_SCROLL_DOWN BUTTON_BOTTOMMIDDLE
275 static int stopwatch
= 0;
276 static long start_at
= 0;
277 static int prev_total
= 0;
278 static bool counting
= false;
279 static int curr_lap
= 0;
280 static int lap_scroll
= 0;
281 static int lap_start
;
282 static int lap_times
[MAX_LAPS
];
284 static void ticks_to_string(int ticks
,int lap
,int buflen
, char * buf
)
286 int hours
, minutes
, seconds
, cs
;
288 hours
= ticks
/ (HZ
* 3600);
289 ticks
-= (HZ
* hours
* 3600);
290 minutes
= ticks
/ (HZ
* 60);
291 ticks
-= (HZ
* minutes
* 60);
292 seconds
= ticks
/ HZ
;
293 ticks
-= (HZ
* seconds
);
297 rb
->snprintf(buf
, buflen
,
298 "%2d:%02d:%02d.%02d",
299 hours
, minutes
, seconds
, cs
);
306 int last_ticks
, last_hours
, last_minutes
, last_seconds
, last_cs
;
307 last_ticks
= lap_times
[(lap
-1)%MAX_LAPS
] - lap_times
[(lap
-2)%MAX_LAPS
];
308 last_hours
= last_ticks
/ (HZ
* 3600);
309 last_ticks
-= (HZ
* last_hours
* 3600);
310 last_minutes
= last_ticks
/ (HZ
* 60);
311 last_ticks
-= (HZ
* last_minutes
* 60);
312 last_seconds
= last_ticks
/ HZ
;
313 last_ticks
-= (HZ
* last_seconds
);
314 last_cs
= last_ticks
;
316 rb
->snprintf(buf
, buflen
,
317 "%2d %2d:%02d:%02d.%02d [%2d:%02d:%02d.%02d]",
318 lap
, hours
, minutes
, seconds
, cs
, last_hours
,
319 last_minutes
, last_seconds
, last_cs
);
323 rb
->snprintf(buf
, buflen
,
324 "%2d %2d:%02d:%02d.%02d",
325 lap
, hours
, minutes
, seconds
, cs
);
331 * Load saved stopwatch state, if exists.
333 void load_stopwatch(void)
337 fd
= rb
->open(STOPWATCH_FILE
, O_RDONLY
);
344 /* variable stopwatch isn't saved/loaded, because it is only used
345 * temporarily in main loop
348 rb
->read(fd
, &start_at
, sizeof(start_at
));
349 rb
->read(fd
, &prev_total
, sizeof(prev_total
));
350 rb
->read(fd
, &counting
, sizeof(counting
));
351 rb
->read(fd
, &curr_lap
, sizeof(curr_lap
));
352 rb
->read(fd
, &lap_scroll
, sizeof(lap_scroll
));
353 rb
->read(fd
, &lap_start
, sizeof(lap_start
));
354 rb
->read(fd
, lap_times
, sizeof(lap_times
));
356 if (counting
&& start_at
> *rb
->current_tick
)
358 /* Stopwatch started in the future? Unlikely; probably started on a
359 * previous session and powered off in-between. We'll keep
360 * everything intact (user can clear manually) but stop the
361 * stopwatch to avoid negative timing.
371 * Save stopwatch state.
373 void save_stopwatch(void)
377 fd
= rb
->open(STOPWATCH_FILE
, O_CREAT
|O_WRONLY
|O_TRUNC
, 0666);
384 /* variable stopwatch isn't saved/loaded, because it is only used
385 * temporarily in main loop
388 rb
->write(fd
, &start_at
, sizeof(start_at
));
389 rb
->write(fd
, &prev_total
, sizeof(prev_total
));
390 rb
->write(fd
, &counting
, sizeof(counting
));
391 rb
->write(fd
, &curr_lap
, sizeof(curr_lap
));
392 rb
->write(fd
, &lap_scroll
, sizeof(lap_scroll
));
393 rb
->write(fd
, &lap_start
, sizeof(lap_start
));
394 rb
->write(fd
, lap_times
, sizeof(lap_times
));
399 enum plugin_status
plugin_start(const void* parameter
)
405 bool update_lap
= true;
410 #ifdef HAVE_LCD_BITMAP
412 rb
->lcd_setfont(FONT_UI
);
413 rb
->lcd_getstringsize("M", NULL
, &h
);
414 lines
= (LCD_HEIGHT
/ h
) - (LAP_Y
);
421 rb
->lcd_clear_display();
427 stopwatch
= prev_total
+ *rb
->current_tick
- start_at
;
431 stopwatch
= prev_total
;
434 ticks_to_string(stopwatch
,0,32,buf
);
435 rb
->lcd_puts(0, TIMER_Y
, buf
);
439 lap_start
= curr_lap
- lap_scroll
;
440 for (lap
= lap_start
; lap
> lap_start
- lines
; lap
--)
444 ticks_to_string(lap_times
[(lap
-1)%MAX_LAPS
],lap
,32,buf
);
445 rb
->lcd_puts_scroll(0, LAP_Y
+ lap_start
- lap
, buf
);
449 rb
->lcd_puts(0, LAP_Y
+ lap_start
- lap
,
460 button
= rb
->button_get(true);
464 button
= rb
->button_get_w_tmo(10);
466 /* Make sure that the jukebox isn't powered off
468 rb
->reset_poweroff_timer();
474 #ifdef STOPWATCH_RC_QUIT
475 case STOPWATCH_RC_QUIT
:
482 /* Stop/Start toggle */
483 case STOPWATCH_START_STOP
:
484 counting
= ! counting
;
487 start_at
= *rb
->current_tick
;
488 stopwatch
= prev_total
+ *rb
->current_tick
- start_at
;
492 prev_total
+= *rb
->current_tick
- start_at
;
493 stopwatch
= prev_total
;
498 case STOPWATCH_RESET_TIMER
:
508 case STOPWATCH_LAP_TIMER
:
509 lap_times
[curr_lap
%MAX_LAPS
] = stopwatch
;
514 /* Scroll Lap timer up */
515 case STOPWATCH_SCROLL_UP
:
523 /* Scroll Lap timer down */
524 case STOPWATCH_SCROLL_DOWN
:
525 if ((lap_scroll
< curr_lap
- lines
) &&
526 (lap_scroll
< (MAX_LAPS
- lines
)) )
534 if (rb
->default_event_handler(button
) == SYS_USB_CONNECTED
)
535 return PLUGIN_USB_CONNECTED
;