A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 Mike Holden
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "plugin.h"
23
24#define TIMER_Y 1
25
26#define LAP_Y TIMER_Y+1
27#define MAX_LAPS 64
28
29#define STOPWATCH_FILE PLUGIN_APPS_DATA_DIR "/stopwatch.dat"
30
31/* variable button definitions */
32#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
33 (CONFIG_KEYPAD == IRIVER_H300_PAD)
34#define STOPWATCH_QUIT BUTTON_OFF
35#define STOPWATCH_START_STOP BUTTON_SELECT
36#define STOPWATCH_RESET_TIMER BUTTON_DOWN
37#define STOPWATCH_LAP_TIMER BUTTON_ON
38#define STOPWATCH_SCROLL_UP BUTTON_RIGHT
39#define STOPWATCH_SCROLL_DOWN BUTTON_LEFT
40#define STOPWATCH_RC_QUIT BUTTON_RC_STOP
41
42#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
43 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
44 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
45#define STOPWATCH_QUIT BUTTON_MENU
46#define STOPWATCH_START_STOP BUTTON_SELECT
47#define STOPWATCH_RESET_TIMER BUTTON_LEFT
48#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
49#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD
50#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK
51
52#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
53#define STOPWATCH_QUIT BUTTON_POWER
54#define STOPWATCH_START_STOP BUTTON_PLAY
55#define STOPWATCH_RESET_TIMER BUTTON_REC
56#define STOPWATCH_LAP_TIMER BUTTON_SELECT
57#define STOPWATCH_SCROLL_UP BUTTON_UP
58#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
59
60#elif CONFIG_KEYPAD == GIGABEAT_PAD
61#define STOPWATCH_QUIT BUTTON_POWER
62#define STOPWATCH_START_STOP BUTTON_SELECT
63#define STOPWATCH_RESET_TIMER BUTTON_A
64#define STOPWATCH_LAP_TIMER BUTTON_MENU
65#define STOPWATCH_SCROLL_UP BUTTON_UP
66#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
67
68#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
69(CONFIG_KEYPAD == SANSA_C200_PAD) || \
70(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
71(CONFIG_KEYPAD == SANSA_M200_PAD)
72#define STOPWATCH_QUIT BUTTON_POWER
73#define STOPWATCH_START_STOP BUTTON_RIGHT
74#define STOPWATCH_RESET_TIMER BUTTON_LEFT
75#define STOPWATCH_LAP_TIMER BUTTON_SELECT
76#define STOPWATCH_SCROLL_UP BUTTON_UP
77#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
78
79#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
80#define STOPWATCH_QUIT (BUTTON_HOME|BUTTON_REPEAT)
81#define STOPWATCH_START_STOP BUTTON_RIGHT
82#define STOPWATCH_RESET_TIMER BUTTON_LEFT
83#define STOPWATCH_LAP_TIMER BUTTON_SELECT
84#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_BACK
85#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_FWD
86
87#elif CONFIG_KEYPAD == IRIVER_H10_PAD
88#define STOPWATCH_QUIT BUTTON_POWER
89#define STOPWATCH_START_STOP BUTTON_PLAY
90#define STOPWATCH_RESET_TIMER BUTTON_REW
91#define STOPWATCH_LAP_TIMER BUTTON_FF
92#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_UP
93#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_DOWN
94
95#elif CONFIG_KEYPAD == MROBE500_PAD
96#define STOPWATCH_QUIT BUTTON_POWER
97
98#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
99#define STOPWATCH_QUIT BUTTON_BACK
100#define STOPWATCH_START_STOP BUTTON_PLAY
101#define STOPWATCH_RESET_TIMER BUTTON_MENU
102#define STOPWATCH_LAP_TIMER BUTTON_SELECT
103#define STOPWATCH_SCROLL_UP BUTTON_UP
104#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
105
106#elif CONFIG_KEYPAD == MROBE100_PAD
107#define STOPWATCH_QUIT BUTTON_POWER
108#define STOPWATCH_START_STOP BUTTON_SELECT
109#define STOPWATCH_RESET_TIMER BUTTON_DISPLAY
110#define STOPWATCH_LAP_TIMER BUTTON_MENU
111#define STOPWATCH_SCROLL_UP BUTTON_UP
112#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
113
114#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
115#define STOPWATCH_QUIT BUTTON_RC_REC
116#define STOPWATCH_START_STOP BUTTON_RC_PLAY
117#define STOPWATCH_RESET_TIMER BUTTON_RC_REW
118#define STOPWATCH_LAP_TIMER BUTTON_RC_FF
119#define STOPWATCH_SCROLL_UP BUTTON_RC_VOL_UP
120#define STOPWATCH_SCROLL_DOWN BUTTON_RC_VOL_DOWN
121#define STOPWATCH_RC_QUIT BUTTON_REC
122
123#elif CONFIG_KEYPAD == COWON_D2_PAD
124#define STOPWATCH_QUIT BUTTON_POWER
125
126#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
127#define STOPWATCH_QUIT BUTTON_BACK
128#define STOPWATCH_START_STOP BUTTON_PLAY
129#define STOPWATCH_RESET_TIMER BUTTON_SELECT
130#define STOPWATCH_LAP_TIMER BUTTON_CUSTOM
131#define STOPWATCH_SCROLL_UP BUTTON_UP
132#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
133
134#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD
135#define STOPWATCH_QUIT BUTTON_POWER
136#define STOPWATCH_START_STOP (BUTTON_PLAY|BUTTON_REL)
137#define STOPWATCH_RESET_TIMER (BUTTON_PLAY|BUTTON_REPEAT)
138#define STOPWATCH_LAP_TIMER BUTTON_MENU
139#define STOPWATCH_SCROLL_UP BUTTON_UP
140#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
141
142#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
143#define STOPWATCH_QUIT BUTTON_POWER
144#define STOPWATCH_START_STOP BUTTON_SELECT
145#define STOPWATCH_RESET_TIMER BUTTON_MENU
146#define STOPWATCH_LAP_TIMER BUTTON_VIEW
147#define STOPWATCH_SCROLL_UP BUTTON_UP
148#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
149
150#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
151#define STOPWATCH_QUIT BUTTON_POWER
152#define STOPWATCH_START_STOP BUTTON_PLAY
153#define STOPWATCH_RESET_TIMER BUTTON_MENU
154#define STOPWATCH_LAP_TIMER BUTTON_NEXT
155#define STOPWATCH_SCROLL_UP BUTTON_UP
156#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
157
158#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
159#define STOPWATCH_QUIT BUTTON_POWER
160#define STOPWATCH_START_STOP BUTTON_PLAY
161#define STOPWATCH_RESET_TIMER BUTTON_MENU
162#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
163#define STOPWATCH_SCROLL_UP BUTTON_UP
164#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
165
166#elif CONFIG_KEYPAD == ONDAVX747_PAD
167#define STOPWATCH_QUIT BUTTON_POWER
168#elif CONFIG_KEYPAD == ONDAVX777_PAD
169#define STOPWATCH_QUIT BUTTON_POWER
170
171#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
172 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
173#define STOPWATCH_QUIT BUTTON_REW
174#define STOPWATCH_START_STOP BUTTON_PLAY
175#define STOPWATCH_RESET_TIMER BUTTON_LEFT
176#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
177#define STOPWATCH_SCROLL_UP BUTTON_UP
178#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
179
180#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
181#define STOPWATCH_QUIT BUTTON_REC
182#define STOPWATCH_START_STOP BUTTON_PLAY
183#define STOPWATCH_RESET_TIMER BUTTON_OK
184#define STOPWATCH_LAP_TIMER BUTTON_MENU
185#define STOPWATCH_SCROLL_UP BUTTON_UP
186#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
187
188#elif CONFIG_KEYPAD == MPIO_HD200_PAD
189#define STOPWATCH_QUIT (BUTTON_REC|BUTTON_PLAY)
190#define STOPWATCH_START_STOP BUTTON_PLAY
191#define STOPWATCH_RESET_TIMER BUTTON_REW
192#define STOPWATCH_LAP_TIMER BUTTON_FF
193#define STOPWATCH_SCROLL_UP BUTTON_VOL_UP
194#define STOPWATCH_SCROLL_DOWN BUTTON_VOL_DOWN
195
196#elif CONFIG_KEYPAD == MPIO_HD300_PAD
197#define STOPWATCH_QUIT (BUTTON_MENU|BUTTON_REPEAT)
198#define STOPWATCH_START_STOP BUTTON_PLAY
199#define STOPWATCH_RESET_TIMER BUTTON_REW
200#define STOPWATCH_LAP_TIMER BUTTON_FF
201#define STOPWATCH_SCROLL_UP BUTTON_UP
202#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
203
204#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
205#define STOPWATCH_QUIT BUTTON_POWER
206#define STOPWATCH_START_STOP BUTTON_PLAYPAUSE
207#define STOPWATCH_RESET_TIMER BUTTON_BACK
208#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
209#define STOPWATCH_SCROLL_UP BUTTON_UP
210#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
211
212#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
213#define STOPWATCH_QUIT BUTTON_POWER
214#define STOPWATCH_START_STOP BUTTON_SELECT
215#define STOPWATCH_RESET_TIMER BUTTON_LEFT
216#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
217#define STOPWATCH_SCROLL_UP BUTTON_UP
218#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
219
220#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
221#define STOPWATCH_QUIT BUTTON_BACK
222#define STOPWATCH_START_STOP BUTTON_SELECT
223#define STOPWATCH_RESET_TIMER BUTTON_MENU
224#define STOPWATCH_LAP_TIMER BUTTON_USER
225#define STOPWATCH_SCROLL_UP BUTTON_UP
226#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
227
228#elif (CONFIG_KEYPAD == HM60X_PAD) || \
229 (CONFIG_KEYPAD == HM801_PAD)
230#define STOPWATCH_QUIT BUTTON_POWER
231#define STOPWATCH_START_STOP BUTTON_SELECT
232#define STOPWATCH_RESET_TIMER BUTTON_LEFT
233#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
234#define STOPWATCH_SCROLL_UP BUTTON_UP
235#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
236
237#elif (CONFIG_KEYPAD == SONY_NWZ_PAD)
238#define STOPWATCH_QUIT BUTTON_POWER
239#define STOPWATCH_START_STOP BUTTON_PLAY
240#define STOPWATCH_RESET_TIMER BUTTON_BACK
241#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
242#define STOPWATCH_SCROLL_UP BUTTON_UP
243#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
244
245#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD)
246#define STOPWATCH_QUIT BUTTON_BACK
247#define STOPWATCH_START_STOP BUTTON_PLAYPAUSE
248#define STOPWATCH_RESET_TIMER BUTTON_SHORTCUT
249#define STOPWATCH_LAP_TIMER BUTTON_SELECT
250#define STOPWATCH_SCROLL_UP BUTTON_UP
251#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
252
253#elif (CONFIG_KEYPAD == AGPTEK_ROCKER_PAD)
254#define STOPWATCH_QUIT BUTTON_POWER
255#define STOPWATCH_START_STOP BUTTON_SELECT
256#define STOPWATCH_RESET_TIMER BUTTON_LEFT
257#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
258#define STOPWATCH_SCROLL_UP BUTTON_UP
259#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
260
261#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD
262#define STOPWATCH_QUIT BUTTON_POWER
263#define STOPWATCH_START_STOP BUTTON_NEXT
264#define STOPWATCH_RESET_TIMER BUTTON_PREV
265#define STOPWATCH_LAP_TIMER BUTTON_PLAY
266#define STOPWATCH_SCROLL_UP BUTTON_HOME
267#define STOPWATCH_SCROLL_DOWN BUTTON_OPTION
268
269#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD
270#define STOPWATCH_QUIT BUTTON_POWER
271#define STOPWATCH_START_STOP BUTTON_NEXT
272#define STOPWATCH_RESET_TIMER BUTTON_PREV
273#define STOPWATCH_LAP_TIMER BUTTON_PLAY
274#define STOPWATCH_SCROLL_UP BUTTON_HOME
275#define STOPWATCH_SCROLL_DOWN BUTTON_OPTION
276
277#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD
278#define STOPWATCH_QUIT BUTTON_POWER
279#define STOPWATCH_START_STOP BUTTON_NEXT
280#define STOPWATCH_RESET_TIMER BUTTON_PREV
281#define STOPWATCH_LAP_TIMER BUTTON_PLAY
282#define STOPWATCH_SCROLL_UP BUTTON_VOL_UP
283#define STOPWATCH_SCROLL_DOWN BUTTON_VOL_DOWN
284
285#elif CONFIG_KEYPAD == EROSQ_PAD
286#define STOPWATCH_QUIT BUTTON_POWER
287#define STOPWATCH_START_STOP BUTTON_PLAY
288#define STOPWATCH_RESET_TIMER BUTTON_BACK
289#define STOPWATCH_LAP_TIMER BUTTON_MENU
290#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_FWD
291#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_BACK
292
293#elif CONFIG_KEYPAD == FIIO_M3K_PAD
294#define STOPWATCH_QUIT BUTTON_POWER
295#define STOPWATCH_START_STOP BUTTON_PLAY
296#define STOPWATCH_RESET_TIMER BUTTON_BACK
297#define STOPWATCH_LAP_TIMER BUTTON_SELECT
298#define STOPWATCH_SCROLL_UP BUTTON_SCROLL_BACK
299#define STOPWATCH_SCROLL_DOWN BUTTON_SCROLL_FWD
300
301#elif CONFIG_KEYPAD == SDL_PAD
302#define STOPWATCH_QUIT BUTTON_MENU
303#define STOPWATCH_START_STOP BUTTON_SELECT
304#define STOPWATCH_RESET_TIMER BUTTON_LEFT
305#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
306#define STOPWATCH_SCROLL_UP BUTTON_UP
307#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
308#elif CONFIG_KEYPAD == MA_PAD
309#define STOPWATCH_QUIT BUTTON_BACK
310#define STOPWATCH_START_STOP BUTTON_PLAY
311#define STOPWATCH_RESET_TIMER BUTTON_LEFT
312#define STOPWATCH_LAP_TIMER BUTTON_RIGHT
313#define STOPWATCH_SCROLL_UP BUTTON_UP
314#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
315
316#elif CONFIG_KEYPAD == RG_NANO_PAD
317#define STOPWATCH_QUIT BUTTON_START
318#define STOPWATCH_START_STOP BUTTON_A
319#define STOPWATCH_RESET_TIMER BUTTON_X
320#define STOPWATCH_LAP_TIMER BUTTON_Y
321#define STOPWATCH_SCROLL_UP BUTTON_UP
322#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN
323
324#else
325#error No keymap defined!
326#endif
327
328#ifdef HAVE_TOUCHSCREEN
329#ifndef STOPWATCH_QUIT
330#define STOPWATCH_QUIT BUTTON_TOPLEFT
331#endif
332#ifndef STOPWATCH_START_STOP
333#define STOPWATCH_START_STOP BUTTON_CENTER
334#endif
335#ifndef STOPWATCH_RESET_TIMER
336#define STOPWATCH_RESET_TIMER BUTTON_MIDRIGHT
337#endif
338#ifndef STOPWATCH_LAP_TIMER
339#define STOPWATCH_LAP_TIMER BUTTON_MIDLEFT
340#endif
341#ifndef STOPWATCH_SCROLL_UP
342#define STOPWATCH_SCROLL_UP BUTTON_TOPMIDDLE
343#endif
344#ifndef STOPWATCH_SCROLL_DOWN
345#define STOPWATCH_SCROLL_DOWN BUTTON_BOTTOMMIDDLE
346#endif
347#endif
348
349static int stopwatch = 0;
350static long start_at = 0;
351static int prev_total = 0;
352static bool counting = false;
353static int curr_lap = 0;
354static int lap_scroll = 0;
355static int lap_start;
356static int lap_times[MAX_LAPS];
357
358static void ticks_to_string(int ticks,int lap,int buflen, char * buf)
359{
360 int hours, minutes, seconds, cs;
361
362 hours = ticks / (HZ * 3600);
363 ticks -= (HZ * hours * 3600);
364 minutes = ticks / (HZ * 60);
365 ticks -= (HZ * minutes * 60);
366 seconds = ticks / HZ;
367 ticks -= (HZ * seconds);
368 cs = ticks;
369 if (!lap)
370 rb->snprintf(buf, buflen,
371 "%2d:%02d:%02d.%02d ", /* add some blank space, in case */
372 hours, minutes, seconds, cs); /* char width differs, since we */
373 /* don't clear the viewport */
374 else if (lap > 1)
375 {
376 int last_ticks, last_hours, last_minutes, last_seconds, last_cs;
377 last_ticks = lap_times[(lap-1)%MAX_LAPS] - lap_times[(lap-2)%MAX_LAPS];
378 last_hours = last_ticks / (HZ * 3600);
379 last_ticks -= (HZ * last_hours * 3600);
380 last_minutes = last_ticks / (HZ * 60);
381 last_ticks -= (HZ * last_minutes * 60);
382 last_seconds = last_ticks / HZ;
383 last_ticks -= (HZ * last_seconds);
384 last_cs = last_ticks;
385
386 rb->snprintf(buf, buflen,
387 "%2d %2d:%02d:%02d.%02d [%2d:%02d:%02d.%02d]",
388 lap, hours, minutes, seconds, cs, last_hours,
389 last_minutes, last_seconds, last_cs);
390 }
391 else
392 rb->snprintf(buf, buflen,
393 "%2d %2d:%02d:%02d.%02d",
394 lap, hours, minutes, seconds, cs);
395}
396
397/*
398 * Load saved stopwatch state, if exists.
399 */
400static void load_stopwatch(void)
401{
402 int fd = rb->open(STOPWATCH_FILE, O_RDONLY);
403 if (fd < 0)
404 return;
405
406 /* variable stopwatch isn't saved/loaded, because it is only used
407 * temporarily in main loop
408 */
409
410 rb->read(fd, &start_at, sizeof(start_at));
411 rb->read(fd, &prev_total, sizeof(prev_total));
412 rb->read(fd, &counting, sizeof(counting));
413 rb->read(fd, &curr_lap, sizeof(curr_lap));
414 rb->read(fd, &lap_scroll, sizeof(lap_scroll));
415 rb->read(fd, &lap_start, sizeof(lap_start));
416 rb->read(fd, lap_times, sizeof(lap_times));
417
418 if (counting && start_at > *rb->current_tick)
419 {
420 /* Stopwatch started in the future? Unlikely; probably started on a
421 * previous session and powered off in-between. We'll keep
422 * everything intact (user can clear manually) but stop the
423 * stopwatch to avoid negative timing.
424 */
425 start_at = 0;
426 counting = false;
427 }
428
429 rb->close(fd);
430}
431
432/*
433 * Save stopwatch state.
434 */
435static void save_stopwatch(void)
436{
437 int fd = rb->open(STOPWATCH_FILE, O_CREAT|O_WRONLY|O_TRUNC, 0666);
438 if (fd < 0)
439 return;
440
441 /* variable stopwatch isn't saved/loaded, because it is only used
442 * temporarily in main loop
443 */
444
445 rb->write(fd, &start_at, sizeof(start_at));
446 rb->write(fd, &prev_total, sizeof(prev_total));
447 rb->write(fd, &counting, sizeof(counting));
448 rb->write(fd, &curr_lap, sizeof(curr_lap));
449 rb->write(fd, &lap_scroll, sizeof(lap_scroll));
450 rb->write(fd, &lap_start, sizeof(lap_start));
451 rb->write(fd, lap_times, sizeof(lap_times));
452
453 rb->close(fd);
454}
455
456enum plugin_status plugin_start(const void* parameter)
457{
458 struct viewport vp, *last_vp;
459 struct screen *display;
460 char buf[32];
461 int button;
462 int lap;
463 int done = false;
464 bool update_lap = true;
465 int lines;
466 int ret = PLUGIN_OK;
467 (void)parameter;
468 int h;
469
470 FOR_NB_SCREENS(i)
471 rb->viewportmanager_theme_enable(i, true, NULL);
472
473 rb->viewport_set_defaults(&vp, SCREEN_MAIN);
474 display = rb->screens[SCREEN_MAIN];
475
476 display->setfont(FONT_UI);
477 display->getstringsize("M", NULL, &h);
478 lines = (vp.height / h) - (LAP_Y);
479
480 load_stopwatch();
481
482 while (!done)
483 {
484 rb->send_event(GUI_EVENT_ACTIONUPDATE, NULL); /* update status bar */
485 if (counting)
486 stopwatch = prev_total + *rb->current_tick - start_at;
487 else
488 stopwatch = prev_total;
489
490 ticks_to_string(stopwatch,0,32,buf);
491 last_vp = display->set_viewport(&vp);
492
493 if(update_lap)
494 {
495 display->clear_viewport();
496 display->puts(0, TIMER_Y, buf);
497 lap_start = curr_lap - lap_scroll;
498 for (lap = lap_start; lap > lap_start - lines; lap--)
499 {
500 if (lap > 0)
501 {
502 ticks_to_string(lap_times[(lap-1)%MAX_LAPS],lap,32,buf);
503 display->puts_scroll(0, LAP_Y + lap_start - lap, buf);
504 }
505 else
506 display->puts(0, LAP_Y + lap_start - lap,
507 " ");
508 }
509 update_lap = false;
510 }
511 else
512 display->puts(0, TIMER_Y, buf);
513 display->update_viewport();
514 display->set_viewport(last_vp);
515 if (!counting)
516 button = rb->button_get_w_tmo(HZ/2);
517 else
518 {
519 button = rb->button_get_w_tmo(HZ/10);
520 rb->reset_poweroff_timer();
521 }
522 switch (button)
523 {
524#ifdef STOPWATCH_RC_QUIT
525 case STOPWATCH_RC_QUIT:
526#endif
527 case STOPWATCH_QUIT:
528 save_stopwatch();
529 done = true;
530 break;
531
532 /* Stop/Start toggle */
533 case STOPWATCH_START_STOP:
534 counting = ! counting;
535 if (counting)
536 {
537 start_at = *rb->current_tick;
538 stopwatch = prev_total + *rb->current_tick - start_at;
539 }
540 else
541 {
542 prev_total += *rb->current_tick - start_at;
543 stopwatch = prev_total;
544 }
545 break;
546
547 /* Reset timer */
548 case STOPWATCH_RESET_TIMER:
549 if (!counting)
550 {
551 prev_total = 0;
552 curr_lap = 0;
553 lap_scroll = 0;
554 update_lap = true;
555 }
556 break;
557
558 /* Lap timer */
559 case STOPWATCH_LAP_TIMER:
560 /*check if we're timing, and start if not*/
561 if (counting)
562 {
563 lap_times[curr_lap%MAX_LAPS] = stopwatch;
564 curr_lap++;
565 update_lap = true;
566 }
567 else
568 {
569 counting = ! counting;
570 start_at = *rb->current_tick;
571 stopwatch = prev_total + *rb->current_tick - start_at;
572 }
573 break;
574
575 /* Scroll Lap timer up */
576 case STOPWATCH_SCROLL_UP:
577 if (lap_scroll > 0)
578 {
579 lap_scroll--;
580 update_lap = true;
581 }
582 break;
583
584 /* Scroll Lap timer down */
585 case STOPWATCH_SCROLL_DOWN:
586 if ((lap_scroll < curr_lap - lines) &&
587 (lap_scroll < (MAX_LAPS - lines)) )
588 {
589 lap_scroll++;
590 update_lap = true;
591 }
592 break;
593
594 default:
595 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
596 ret = PLUGIN_USB_CONNECTED;
597 break;
598 }
599 }
600 FOR_NB_SCREENS(i)
601 rb->viewportmanager_theme_undo(i, false);
602 return ret;
603}