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 *
11 * Copyright (C) 2006 Alexander Spyridakis, Hristo Kovachev
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "version.h"
24#include "plugin.h"
25#include "lang_enum.h"
26
27/* matches struct in powermgmt.h */
28struct battery_tables_t {
29 unsigned short * const history;
30 unsigned short * const disksafe;
31 unsigned short * const shutoff;
32 unsigned short * const discharge;
33#if CONFIG_CHARGING
34 unsigned short * const charge;
35#endif
36 const unsigned short elems;
37 bool isdefault;
38};
39
40#define BATTERY_LEVELS_DEFAULT ROCKBOX_DIR"/battery_levels.default"
41#define BATTERY_LEVELS_USER ROCKBOX_DIR"/battery_levels.cfg"
42
43#define BATTERY_LOG HOME_DIR "/battery_bench.txt"
44#define BUF_SIZE 16000
45
46#define EV_EXIT 1337
47
48/* seems to work with 1300, but who knows... */
49#define THREAD_STACK_SIZE 4*DEFAULT_STACK_SIZE
50
51#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
52 (CONFIG_KEYPAD == IRIVER_H300_PAD)
53
54#define BATTERY_ON BUTTON_ON
55#define BATTERY_RC_ON BUTTON_RC_ON
56
57#define BATTERY_OFF BUTTON_OFF
58#define BATTERY_RC_OFF BUTTON_RC_STOP
59
60#define BATTERY_ON_TXT "PLAY - start"
61#define BATTERY_OFF_TXT "STOP"
62
63#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
64 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
65 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
66
67#define BATTERY_ON BUTTON_PLAY
68#define BATTERY_OFF BUTTON_MENU
69#define BATTERY_ON_TXT "PLAY - start"
70#define BATTERY_OFF_TXT "MENU"
71
72#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD || \
73 CONFIG_KEYPAD == AGPTEK_ROCKER_PAD
74
75#define BATTERY_ON BUTTON_SELECT
76#define BATTERY_OFF BUTTON_POWER
77#define BATTERY_ON_TXT "SELECT - start"
78#define BATTERY_OFF_TXT "POWER"
79
80#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
81 (CONFIG_KEYPAD == SANSA_C200_PAD) || \
82 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
83 (CONFIG_KEYPAD == SANSA_M200_PAD)
84#define BATTERY_ON BUTTON_SELECT
85#define BATTERY_OFF BUTTON_POWER
86#define BATTERY_ON_TXT "SELECT - start"
87#define BATTERY_OFF_TXT "POWER"
88
89#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
90#define BATTERY_ON BUTTON_SELECT
91#define BATTERY_OFF BUTTON_HOME
92#define BATTERY_ON_TXT "SELECT - start"
93#define BATTERY_OFF_TXT "HOME"
94
95#elif (CONFIG_KEYPAD == IRIVER_H10_PAD || \
96 CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD || \
97 CONFIG_KEYPAD == SONY_NWZ_PAD || \
98 CONFIG_KEYPAD == XDUOO_X3_PAD || \
99 CONFIG_KEYPAD == IHIFI_770_PAD || \
100 CONFIG_KEYPAD == IHIFI_800_PAD || \
101 CONFIG_KEYPAD == XDUOO_X3II_PAD || \
102 CONFIG_KEYPAD == XDUOO_X20_PAD || \
103 CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD || \
104 CONFIG_KEYPAD == EROSQ_PAD)
105
106#define BATTERY_ON BUTTON_PLAY
107#define BATTERY_OFF BUTTON_POWER
108#define BATTERY_ON_TXT "PLAY - start"
109#define BATTERY_OFF_TXT "POWER"
110
111#elif CONFIG_KEYPAD == GIGABEAT_PAD
112
113#define BATTERY_ON BUTTON_SELECT
114#define BATTERY_OFF BUTTON_POWER
115#define BATTERY_ON_TXT "SELECT - start"
116#define BATTERY_OFF_TXT "POWER"
117
118#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \
119 || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD \
120 || CONFIG_KEYPAD == CREATIVE_ZEN_PAD
121
122#define BATTERY_ON BUTTON_SELECT
123#define BATTERY_OFF BUTTON_BACK
124#define BATTERY_ON_TXT "SELECT - start"
125#define BATTERY_OFF_TXT "BACK"
126
127#elif CONFIG_KEYPAD == MROBE500_PAD
128
129#define BATTERY_OFF BUTTON_POWER
130#define BATTERY_OFF_TXT "POWER"
131
132#elif CONFIG_KEYPAD == MROBE100_PAD
133
134#define BATTERY_ON BUTTON_SELECT
135#define BATTERY_OFF BUTTON_POWER
136#define BATTERY_ON_TXT "SELECT - start"
137#define BATTERY_OFF_TXT "POWER"
138
139#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
140
141#define BATTERY_ON BUTTON_PLAY
142#define BATTERY_OFF BUTTON_REC
143#define BATTERY_RC_ON BUTTON_RC_PLAY
144#define BATTERY_RC_OFF BUTTON_RC_REC
145#define BATTERY_ON_TXT "PLAY - start"
146#define BATTERY_OFF_TXT "REC"
147
148#elif CONFIG_KEYPAD == COWON_D2_PAD
149
150#define BATTERY_OFF BUTTON_POWER
151#define BATTERY_OFF_TXT "POWER"
152
153#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
154#define BATTERY_ON BUTTON_PLAY
155#define BATTERY_ON_TXT "PLAY - start"
156#define BATTERY_OFF BUTTON_BACK
157#define BATTERY_OFF_TXT "BACK"
158
159#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
160
161#define BATTERY_ON BUTTON_MENU
162#define BATTERY_OFF BUTTON_POWER
163#define BATTERY_ON_TXT "MENU - start"
164#define BATTERY_OFF_TXT "POWER"
165
166#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
167
168#define BATTERY_ON BUTTON_MENU
169#define BATTERY_OFF BUTTON_POWER
170#define BATTERY_ON_TXT "MENU - start"
171#define BATTERY_OFF_TXT "POWER"
172
173#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
174
175#define BATTERY_ON BUTTON_MENU
176#define BATTERY_OFF BUTTON_POWER
177#define BATTERY_ON_TXT "MENU - start"
178#define BATTERY_OFF_TXT "POWER"
179
180#elif CONFIG_KEYPAD == ONDAVX747_PAD
181
182#define BATTERY_OFF BUTTON_POWER
183#define BATTERY_OFF_TXT "POWER"
184#elif CONFIG_KEYPAD == ONDAVX777_PAD
185
186#define BATTERY_OFF BUTTON_POWER
187#define BATTERY_OFF_TXT "POWER"
188
189#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \
190 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD)
191
192#define BATTERY_ON BUTTON_LEFT
193#define BATTERY_OFF BUTTON_RIGHT
194#define BATTERY_ON_TXT "LEFT"
195#define BATTERY_OFF_TXT "RIGHT"
196
197#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
198
199#define BATTERY_ON BUTTON_PLAY
200#define BATTERY_OFF BUTTON_REC
201#define BATTERY_ON_TXT "PLAY - start"
202#define BATTERY_OFF_TXT "REC"
203
204#elif CONFIG_KEYPAD == MPIO_HD200_PAD
205#define BATTERY_ON BUTTON_PLAY
206#define BATTERY_OFF BUTTON_REC
207#define BATTERY_ON_TXT "PLAY - start"
208#define BATTERY_OFF_TXT "REC"
209
210#elif CONFIG_KEYPAD == MPIO_HD300_PAD
211#define BATTERY_ON BUTTON_PLAY
212#define BATTERY_OFF BUTTON_REC
213#define BATTERY_ON_TXT "PLAY - start"
214#define BATTERY_OFF_TXT "REC"
215
216#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
217#define BATTERY_ON BUTTON_PLAYPAUSE
218#define BATTERY_OFF BUTTON_POWER
219#define BATTERY_ON_TXT "PLAYPAUSE - start"
220#define BATTERY_OFF_TXT "POWER"
221
222#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD
223#define BATTERY_ON BUTTON_SELECT
224#define BATTERY_OFF BUTTON_POWER
225#define BATTERY_ON_TXT "SELECT - start"
226#define BATTERY_OFF_TXT "POWER"
227
228#elif (CONFIG_KEYPAD == HM60X_PAD) || (CONFIG_KEYPAD == HM801_PAD)
229#define BATTERY_ON BUTTON_SELECT
230#define BATTERY_OFF BUTTON_POWER
231#define BATTERY_ON_TXT "SELECT - start"
232
233#define BATTERY_OFF_TXT "POWER"
234
235#elif CONFIG_KEYPAD == DX50_PAD
236#define BATTERY_ON BUTTON_PLAY
237#define BATTERY_OFF BUTTON_POWER_LONG
238#define BATTERY_OFF_TXT "Power Long"
239#define BATTERY_ON_TXT "Play - start"
240
241#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
242#define BATTERY_ON BUTTON_MENU
243#define BATTERY_OFF BUTTON_POWER
244#define BATTERY_OFF_TXT "Power"
245#define BATTERY_ON_TXT "Menu - start"
246
247#elif CONFIG_KEYPAD == FIIO_M3K_PAD
248#define BATTERY_ON BUTTON_PLAY
249#define BATTERY_OFF BUTTON_POWER
250#define BATTERY_ON_TXT "Play"
251#define BATTERY_OFF_TXT "Power"
252
253#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
254/* use touchscreen */
255
256#elif CONFIG_KEYPAD == MA_PAD
257#define BATTERY_ON BUTTON_PLAY
258#define BATTERY_OFF BUTTON_BACK
259#define BATTERY_ON_TXT "Play"
260#define BATTERY_OFF_TXT "Back"
261
262#elif CONFIG_KEYPAD == RG_NANO_PAD
263#define BATTERY_ON BUTTON_A
264#define BATTERY_OFF BUTTON_X
265#define BATTERY_ON_TXT "A"
266#define BATTERY_OFF_TXT "X"
267
268#else
269#error "No keymap defined!"
270#endif
271
272#if defined(HAVE_TOUCHSCREEN)
273
274#ifndef BATTERY_ON
275#define BATTERY_ON BUTTON_CENTER
276#endif
277#ifndef BATTERY_OFF
278#define BATTERY_OFF BUTTON_TOPLEFT
279#endif
280#ifndef BATTERY_ON_TXT
281#define BATTERY_ON_TXT "CENTRE - start"
282#endif
283#ifndef BATTERY_OFF_TXT
284#define BATTERY_OFF_TXT "TOPLEFT"
285#endif
286
287#endif
288
289/****************************** Plugin Entry Point ****************************/
290long start_tick;
291
292/* Struct for battery information */
293static struct batt_info
294{
295 /* the size of the struct elements is optimised to make the struct size
296 * a power of 2 */
297 unsigned secs;
298 int eta;
299 int voltage;
300#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
301 int current;
302#endif
303 short level;
304 unsigned short flags;
305} bat[BUF_SIZE/sizeof(struct batt_info)];
306
307#define BUF_ELEMENTS (sizeof(bat)/sizeof(struct batt_info))
308
309
310static struct
311{
312 unsigned int id; /* worker thread id */
313 long stack[THREAD_STACK_SIZE / sizeof(long)];
314} gThread;
315
316static struct event_queue thread_q SHAREDBSS_ATTR;
317static bool in_usb_mode;
318static unsigned int buf_idx;
319
320static int exit_tsr(bool reenter)
321{
322 int exit_status;
323 long button;
324
325 rb->lcd_clear_display();
326 rb->lcd_puts_scroll(0, 0, "Batt.Bench is currently running.");
327 rb->lcd_puts_scroll(0, 1, "Press " BATTERY_OFF_TXT " to cancel the test");
328 rb->lcd_puts_scroll(0, 2, "Anything else will resume");
329 if(rb->global_settings->talk_menu)
330 rb->talk_id(VOICE_BATTERY_BENCH_IS_ALREADY_RUNNING, true);
331 rb->lcd_update();
332
333 while (1)
334 {
335 button = rb->button_get(true);
336 if (IS_SYSEVENT(button))
337 continue;
338 if (button == BATTERY_OFF)
339 {
340 rb->queue_post(&thread_q, EV_EXIT, 0);
341 rb->thread_wait(gThread.id);
342 /* remove the thread's queue from the broadcast list */
343 rb->queue_delete(&thread_q);
344 exit_status = (reenter ? PLUGIN_TSR_TERMINATE : PLUGIN_TSR_SUSPEND);
345
346 }
347 else exit_status = PLUGIN_TSR_CONTINUE;
348
349 break;
350 }
351 FOR_NB_SCREENS(idx)
352 rb->screens[idx]->scroll_stop();
353
354 return exit_status;
355}
356
357#define BIT_CHARGER 0x1
358#define BIT_CHARGING 0x2
359#define BIT_USB_POWER 0x4
360
361#define HMS(x) (x)/3600,((x)%3600)/60,((x)%3600)%60
362
363#if CONFIG_CHARGING || defined(HAVE_USB_POWER)
364static unsigned int charge_state(void)
365{
366 unsigned int ret = 0;
367#if CONFIG_CHARGING
368 if (rb->charger_inserted())
369 ret = BIT_CHARGER;
370#if CONFIG_CHARGING >= CHARGING_MONITOR
371 if (rb->charging_state())
372 ret |= BIT_CHARGING;
373#endif
374#endif
375 /* USB insertion means nothing if USB cannot power the device */
376#ifdef HAVE_USB_POWER
377 if (rb->usb_inserted())
378 ret |= BIT_USB_POWER;
379#endif
380 return ret;
381}
382#endif
383
384
385static void flush_buffer(void)
386{
387 int fd;
388 unsigned int i;
389
390 /* don't access the disk when in usb mode, or when no data is available */
391 if (in_usb_mode || (buf_idx == 0))
392 return;
393
394 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND, 0666);
395 if (fd < 0)
396 return;
397
398 for (i = 0; i < buf_idx; i++)
399 {
400 rb->fdprintf(fd,
401 "%02d:%02d:%02d, %05d, %03d%%, "
402 "%02d:%02d, %04d, "
403#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
404 " %04d, "
405#endif
406#if CONFIG_CHARGING
407 " %c"
408#if CONFIG_CHARGING >= CHARGING_MONITOR
409 ", %c"
410#endif
411#endif
412#ifdef HAVE_USB_POWER
413 ", %c"
414#endif
415 "\n",
416
417 HMS(bat[i].secs), bat[i].secs, bat[i].level,
418 bat[i].eta / 60, bat[i].eta % 60,
419 bat[i].voltage
420#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
421 , bat[i].current
422#endif
423#if CONFIG_CHARGING
424 , (bat[i].flags & BIT_CHARGER) ? 'A' : '-'
425#if CONFIG_CHARGING >= CHARGING_MONITOR
426 , (bat[i].flags & BIT_CHARGING) ? 'C' : '-'
427#endif
428#endif
429#ifdef HAVE_USB_POWER
430 , (bat[i].flags & BIT_USB_POWER) ? 'U' : '-'
431#endif
432 );
433 }
434 rb->close(fd);
435
436 buf_idx = 0;
437}
438
439
440static void thread(void)
441{
442 bool exit = false;
443 char *exit_reason = "unknown";
444 long sleep_time = 60 * HZ;
445 struct queue_event ev;
446 int fd;
447
448 in_usb_mode = false;
449 buf_idx = 0;
450
451 while (!exit)
452 {
453 /* add data to buffer */
454 if (buf_idx < BUF_ELEMENTS)
455 {
456 bat[buf_idx].secs = (*rb->current_tick - start_tick) / HZ;
457 bat[buf_idx].level = rb->battery_level();
458 bat[buf_idx].eta = rb->battery_time();
459 bat[buf_idx].voltage = rb->battery_voltage();
460#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
461 bat[buf_idx].current = rb->battery_current();
462#endif
463#if CONFIG_CHARGING || defined(HAVE_USB_POWER)
464 bat[buf_idx].flags = charge_state();
465#endif
466 buf_idx++;
467#ifdef USING_STORAGE_CALLBACK
468 rb->register_storage_idle_func(flush_buffer);
469#endif
470 }
471
472 /* What to do when the measurement buffer is full:
473 1) save our measurements to disk but waste some power doing so?
474 2) throw away measurements to save some power?
475 The choice made here is to save the measurements. It is quite unusual
476 for this to occur because it requires > 16 hours of no disk activity.
477 */
478 if (buf_idx == BUF_ELEMENTS) {
479 flush_buffer();
480 }
481
482 /* sleep some time until next measurement */
483 rb->queue_wait_w_tmo(&thread_q, &ev, sleep_time);
484 switch (ev.id)
485 {
486 case SYS_USB_CONNECTED:
487 in_usb_mode = true;
488 rb->usb_acknowledge(SYS_USB_CONNECTED_ACK);
489 break;
490 case SYS_USB_DISCONNECTED:
491 in_usb_mode = false;
492 break;
493 case SYS_POWEROFF:
494 case SYS_REBOOT:
495 exit_reason = "power off";
496 exit = true;
497 break;
498 case EV_EXIT:
499 rb->splash(HZ, "Exiting battery_bench...");
500 exit_reason = "plugin exit";
501 exit = true;
502 break;
503 }
504 }
505
506#ifdef USING_STORAGE_CALLBACK
507 /* unregister flush callback and flush to disk */
508 rb->unregister_storage_idle_func(flush_buffer, true);
509#else
510 flush_buffer();
511#endif
512
513 /* log end of bench and exit reason */
514 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT | O_APPEND, 0666);
515 if (fd >= 0)
516 {
517 rb->fdprintf(fd, "--Battery bench ended, reason: %s--\n", exit_reason);
518 rb->close(fd);
519 }
520}
521
522
523typedef void (*plcdfunc)(int x, int y, const unsigned char *str);
524
525static void put_centered_str(const char* str, plcdfunc putsxy, int lcd_width, int line)
526{
527 int strwdt, strhgt;
528 rb->lcd_getstringsize(str, &strwdt, &strhgt);
529 putsxy((lcd_width - strwdt)/2, line*(strhgt), str);
530}
531
532void do_export_battery_tables(void)
533{
534 size_t elems = rb->device_battery_tables->elems;
535 if (!rb->device_battery_tables->isdefault)
536 return; /* no need to print out non-defaults */
537 unsigned int i;
538 int fd;
539 /* write out the default battery levels file */
540 if (!rb->file_exists(BATTERY_LEVELS_DEFAULT))
541 {
542 fd = rb->open(BATTERY_LEVELS_DEFAULT, O_WRONLY | O_CREAT | O_TRUNC, 0666);
543 if (fd >= 0)
544 {
545 rb->fdprintf(fd, "# Rename to %s\n# " MODEL_NAME " Battery Levels (%s)\n\n",
546 BATTERY_LEVELS_USER, rb->rbversion);
547
548 rb->fdprintf(fd, "# Battery voltage(millivolt) of {");
549 for(i= 0;i < elems;i++)
550 {
551 rb->fdprintf(fd, "%u%%, ", i * 10);
552 }
553 rb->lseek(fd, -2, SEEK_CUR); /*remove last comma */
554 rb->fdprintf(fd, "} when charging %sabled\n", "dis");
555 rb->fdprintf(fd, "discharge: {");
556 for(i= 0;i < elems;i++)
557 {
558 rb->fdprintf(fd, "%u, ", rb->device_battery_tables->discharge[i]);
559 }
560 rb->lseek(fd, -2, SEEK_CUR); /*remove last comma */
561 rb->fdprintf(fd, "}\n\n");
562#if CONFIG_CHARGING
563 rb->fdprintf(fd, "# Battery voltage(millivolt) of {");
564 for(i= 0;i < elems;i++)
565 {
566 rb->fdprintf(fd, "%u%%, ", i * 10);
567 }
568 rb->lseek(fd, -2, SEEK_CUR); /*remove last comma */
569 rb->fdprintf(fd, "} when charging %sabled\n", "en");
570 rb->fdprintf(fd, "charge: {");
571 for(i= 0;i < elems;i++)
572 {
573 rb->fdprintf(fd, "%u, ", rb->device_battery_tables->charge[i]);
574 }
575 rb->lseek(fd, -2, SEEK_CUR); /*remove last comma */
576 rb->fdprintf(fd, "}\n\n");
577#endif
578
579 rb->fdprintf(fd, "# WARNING 'shutoff' and 'disksafe' levels protect " \
580 "from battery over-discharge and dataloss\n\n");
581
582 rb->fdprintf(fd, "# Battery voltage(millivolt) lower than this %s\n",
583 "player will shutdown");
584
585 rb->fdprintf(fd, "#shutoff: %d\n\n", *rb->device_battery_tables->shutoff);
586
587 rb->fdprintf(fd, "# Battery voltage(millivolt) lower than this %s\n",
588 "won't access the disk to write");
589 rb->fdprintf(fd, "#disksafe: %d\n\n", *rb->device_battery_tables->disksafe);
590
591 rb->close(fd);
592 }
593 }
594}
595
596enum plugin_status plugin_start(const void* parameter)
597{
598 int button, fd;
599 bool resume = false;
600 bool on = false;
601 start_tick = *rb->current_tick;
602 int i;
603 const char *msgs[] = { "Battery Benchmark","Check file", BATTERY_LOG,
604 "for more info", BATTERY_ON_TXT, BATTERY_OFF_TXT " - quit" };
605
606 if (parameter == rb->plugin_tsr)
607 {
608 resume = true;
609 on = true;
610 }
611
612 rb->lcd_clear_display();
613 rb->lcd_setfont(FONT_SYSFIXED);
614
615 for (i = 0; i<(int)(sizeof(msgs)/sizeof(char *)); i++)
616 put_centered_str(msgs[i],rb->lcd_putsxy,LCD_WIDTH,i+1);
617 if(rb->global_settings->talk_menu)
618 rb->talk_id(VOICE_BAT_BENCH_KEYS, true);
619 rb->lcd_update();
620
621#ifdef HAVE_REMOTE_LCD
622 rb->lcd_remote_clear_display();
623 put_centered_str(msgs[0],rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,0);
624 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-2],
625 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,1);
626 put_centered_str(msgs[sizeof(msgs)/sizeof(char*)-1],
627 rb->lcd_remote_putsxy,LCD_REMOTE_WIDTH,2);
628 rb->lcd_remote_update();
629#endif
630 if (!resume)
631 {
632 do_export_battery_tables();
633 do
634 {
635 button = rb->button_get(true);
636 switch (button)
637 {
638 case BATTERY_ON:
639 #ifdef BATTERY_RC_ON
640 case BATTERY_RC_ON:
641 #endif
642 on = true;
643 break;
644 case BATTERY_OFF:
645 #ifdef BATTERY_RC_OFF
646 case BATTERY_RC_OFF:
647 #endif
648 return PLUGIN_OK;
649
650 default:
651 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
652 return PLUGIN_USB_CONNECTED;
653 }
654 }while(!on);
655 }
656 fd = rb->open(BATTERY_LOG, O_RDONLY);
657 if (fd < 0)
658 {
659 fd = rb->open(BATTERY_LOG, O_RDWR | O_CREAT, 0666);
660 if (fd >= 0)
661 {
662
663 rb->fdprintf(fd,
664 "# This plugin will log your battery performance in a\n"
665 "# file (%s) every minute.\n"
666 "# To properly test your battery:\n"
667 "# 1) Select and playback an album. "
668 "(Be sure to be more than the player's buffer)\n"
669 "# 2) Set to repeat.\n"
670 "# 3) Let the player run completely out of battery.\n"
671 "# 4) Recharge and copy (or whatever you want) the txt file to "
672 "your computer.\n"
673 "# Now you can make graphs with the data of the battery log.\n"
674 "# Do not enter another plugin during the test or else the \n"
675 "# logging activity will end.\n\n"
676 "# P.S: You can decide how you will make your tests.\n"
677 "# Just don't open another plugin to be sure that your log "
678 "will continue.\n\n",BATTERY_LOG);
679 rb->fdprintf(fd,
680 "# Battery bench run for %s version %s\n\n"
681 ,MODEL_NAME,rb->rbversion);
682
683 rb->fdprintf(fd, "# Battery type: %d mAh Buffer Entries: %d\n",
684#if BATTERY_CAPACITY_INC > 0
685 rb->global_settings->battery_capacity,
686#else
687 BATTERY_CAPACITY_DEFAULT,
688#endif
689 (int)BUF_ELEMENTS);
690
691 rb->fdprintf(fd, "# Rockbox has been running for %02d:%02d:%02d\n",
692 HMS((unsigned)start_tick/HZ));
693
694 rb->fdprintf(fd,
695 "# Time:, Seconds:, Level:, Time Left:, Voltage[mV]:"
696#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE
697 ", Current[mA]:"
698#endif
699#if CONFIG_CHARGING
700 ", C:"
701#endif
702#if CONFIG_CHARGING >= CHARGING_MONITOR
703 ", S:"
704#endif
705#ifdef HAVE_USB_POWER
706 ", U:"
707#endif
708 "\n");
709 rb->close(fd);
710 }
711 else
712 {
713 rb->splash(HZ / 2, "Cannot create file!");
714 return PLUGIN_ERROR;
715 }
716 }
717 else
718 {
719 rb->close(fd);
720 fd = rb->open(BATTERY_LOG, O_RDWR | O_APPEND);
721 rb->fdprintf(fd, "\n# --File already present. Resuming Benchmark--\n");
722 rb->fdprintf(fd,
723 "# Battery bench run for %s version %s\n\n"
724 ,MODEL_NAME,rb->rbversion);
725 rb->fdprintf(fd, "# Rockbox has been running for %02d:%02d:%02d\n",
726 HMS((unsigned)start_tick/HZ));
727 rb->close(fd);
728 }
729
730 rb->memset(&gThread, 0, sizeof(gThread));
731 rb->queue_init(&thread_q, true); /* put the thread's queue in the bcast list */
732 gThread.id = rb->create_thread(thread, gThread.stack, sizeof(gThread.stack),
733 0, "Battery Benchmark"
734 IF_PRIO(, PRIORITY_BACKGROUND)
735 IF_COP(, CPU));
736
737 if (gThread.id == 0 || gThread.id == UINT_MAX)
738 {
739 rb->splash(HZ, "Cannot create thread!");
740 return PLUGIN_ERROR;
741 }
742
743 rb->plugin_tsr(exit_tsr);
744
745 return PLUGIN_OK;
746}