A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 746 lines 22 kB view raw
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}