A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1058 lines 33 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2003 Lee Pilgrim 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 **************************************************************************/ 20#include "plugin.h" 21#include "fixedpoint.h" 22#include "lib/playback_control.h" 23#include "lib/helper.h" 24#include "lib/pluginlib_exit.h" 25 26 27 28/* variable button definitions */ 29#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 30 (CONFIG_KEYPAD == IRIVER_H300_PAD) 31#define VUMETER_QUIT BUTTON_OFF 32#define VUMETER_HELP BUTTON_ON 33#define VUMETER_MENU BUTTON_SELECT 34#define VUMETER_MENU2 BUTTON_MODE 35#define VUMETER_UP BUTTON_UP 36#define VUMETER_DOWN BUTTON_DOWN 37#define LABEL_HELP "PLAY" 38#define LABEL_QUIT "STOP" 39#define LABEL_MENU "SELECT,MODE" 40#define LABEL_VOLUME "UP/DOWN" 41 42#define VUMETER_RC_QUIT BUTTON_RC_STOP 43 44#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 45 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 46 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 47#define VUMETER_QUIT BUTTON_MENU 48#define VUMETER_HELP BUTTON_PLAY 49#define VUMETER_MENU BUTTON_SELECT 50#define VUMETER_UP BUTTON_SCROLL_FWD 51#define VUMETER_DOWN BUTTON_SCROLL_BACK 52#define LABEL_HELP "PLAY" 53#define LABEL_QUIT "MENU" 54#define LABEL_MENU "SELECT" 55#define LABEL_VOLUME "Wheel" 56 57#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 58#define VUMETER_QUIT BUTTON_POWER 59#define VUMETER_HELP BUTTON_A 60#define VUMETER_MENU BUTTON_MENU 61#define VUMETER_UP BUTTON_UP 62#define VUMETER_DOWN BUTTON_DOWN 63#define LABEL_HELP "A" 64#define LABEL_QUIT "POWER" 65#define LABEL_MENU "MENU" 66#define LABEL_VOLUME "UP/DOWN" 67 68#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 69#define VUMETER_QUIT BUTTON_POWER 70#define VUMETER_HELP BUTTON_REC 71#define VUMETER_MENU BUTTON_SELECT 72#define VUMETER_UP BUTTON_SCROLL_FWD 73#define VUMETER_DOWN BUTTON_SCROLL_BACK 74#define LABEL_HELP "REC" 75#define LABEL_QUIT "POWER" 76#define LABEL_MENU "SELECT" 77#define LABEL_VOLUME "Wheel" 78 79#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 80#define VUMETER_QUIT (BUTTON_HOME|BUTTON_REPEAT) 81#define VUMETER_HELP BUTTON_SELECT|BUTTON_REPEAT 82#define VUMETER_MENU BUTTON_SELECT|BUTTON_REL 83#define VUMETER_UP BUTTON_SCROLL_FWD 84#define VUMETER_DOWN BUTTON_SCROLL_BACK 85#define LABEL_HELP "Hold Select" 86#define LABEL_QUIT "HOME" 87#define LABEL_MENU "Select" 88#define LABEL_VOLUME "Scrollwheel" 89 90#elif (CONFIG_KEYPAD == SANSA_C200_PAD) 91#define VUMETER_QUIT BUTTON_POWER 92#define VUMETER_HELP BUTTON_REC 93#define VUMETER_MENU BUTTON_SELECT 94#define VUMETER_UP BUTTON_VOL_UP 95#define VUMETER_DOWN BUTTON_VOL_DOWN 96#define LABEL_HELP "REC" 97#define LABEL_QUIT "POWER" 98#define LABEL_MENU "SELECT" 99#define LABEL_VOLUME "VOL UP/DN" 100 101#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD) 102#define VUMETER_QUIT BUTTON_POWER 103#define VUMETER_HELP BUTTON_HOME 104#define VUMETER_MENU BUTTON_SELECT 105#define VUMETER_UP BUTTON_VOL_UP 106#define VUMETER_DOWN BUTTON_VOL_DOWN 107#define LABEL_HELP "HOME" 108#define LABEL_QUIT "POWER" 109#define LABEL_MENU "SELECT" 110#define LABEL_VOLUME "VOL UP/DN" 111 112#elif (CONFIG_KEYPAD == SANSA_M200_PAD) 113#define VUMETER_QUIT BUTTON_POWER 114#define VUMETER_HELP (BUTTON_SELECT | BUTTON_UP) 115#define VUMETER_MENU (BUTTON_SELECT | BUTTON_REL) 116#define VUMETER_UP BUTTON_VOL_UP 117#define VUMETER_DOWN BUTTON_VOL_DOWN 118#define LABEL_HELP "SELECT + UP" 119#define LABEL_QUIT "POWER" 120#define LABEL_MENU "SELECT" 121#define LABEL_VOLUME "VOL UP/DN" 122 123#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD 124#define VUMETER_QUIT BUTTON_POWER 125#define VUMETER_HELP BUTTON_PLAY 126#define VUMETER_MENU BUTTON_SELECT 127#define VUMETER_UP BUTTON_UP 128#define VUMETER_DOWN BUTTON_DOWN 129#define LABEL_HELP "PLAY" 130#define LABEL_QUIT "POWER" 131#define LABEL_MENU "SELECT" 132#define LABEL_VOLUME "UP/DOWN" 133 134#elif CONFIG_KEYPAD == IRIVER_H10_PAD 135#define VUMETER_QUIT BUTTON_POWER 136#define VUMETER_HELP BUTTON_PLAY 137#define VUMETER_MENU BUTTON_REW 138#define VUMETER_UP BUTTON_SCROLL_UP 139#define VUMETER_DOWN BUTTON_SCROLL_DOWN 140#define LABEL_HELP "PLAY" 141#define LABEL_QUIT "POWER" 142#define LABEL_MENU "REW" 143#define LABEL_VOLUME "Scroller" 144 145#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) 146#define VUMETER_QUIT BUTTON_BACK 147#define VUMETER_HELP BUTTON_NEXT 148#define VUMETER_MENU BUTTON_MENU 149#define VUMETER_UP BUTTON_UP 150#define VUMETER_DOWN BUTTON_DOWN 151#define LABEL_HELP "NEXT" 152#define LABEL_QUIT "BACK" 153#define LABEL_MENU "MENU" 154#define LABEL_VOLUME "UP/DOWN" 155 156#elif (CONFIG_KEYPAD == MROBE100_PAD) 157#define VUMETER_QUIT BUTTON_POWER 158#define VUMETER_HELP BUTTON_DISPLAY 159#define VUMETER_MENU BUTTON_MENU 160#define VUMETER_UP BUTTON_UP 161#define VUMETER_DOWN BUTTON_DOWN 162#define LABEL_HELP "DISPLAY" 163#define LABEL_QUIT "POWER" 164#define LABEL_MENU "MENU" 165#define LABEL_VOLUME "UP/DOWN" 166 167#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 168#define VUMETER_QUIT BUTTON_RC_REC 169#define VUMETER_HELP BUTTON_RC_MODE 170#define VUMETER_MENU BUTTON_RC_MENU 171#define VUMETER_UP BUTTON_RC_VOL_UP 172#define VUMETER_DOWN BUTTON_RC_VOL_DOWN 173#define LABEL_HELP "MODE" 174#define LABEL_QUIT "REC" 175#define LABEL_MENU "MENU" 176#define LABEL_VOLUME "VOL UP/DN" 177 178#elif CONFIG_KEYPAD == COWON_D2_PAD 179#define VUMETER_QUIT BUTTON_POWER 180#define VUMETER_MENU BUTTON_MENU 181#define LABEL_QUIT "POWER" 182#define LABEL_MENU "MENU" 183 184#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 185#define VUMETER_QUIT BUTTON_BACK 186#define VUMETER_HELP BUTTON_SELECT 187#define VUMETER_MENU BUTTON_MENU 188#define VUMETER_UP BUTTON_UP 189#define VUMETER_DOWN BUTTON_DOWN 190#define LABEL_HELP "MIDDLE" 191#define LABEL_QUIT "BACK" 192#define LABEL_MENU "MENU" 193#define LABEL_VOLUME "UP/DOWN" 194 195#elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) 196#define VUMETER_QUIT BUTTON_POWER 197#define VUMETER_HELP BUTTON_MENU|BUTTON_REPEAT 198#define VUMETER_MENU BUTTON_MENU|BUTTON_REL 199#define VUMETER_UP BUTTON_VOL_UP 200#define VUMETER_DOWN BUTTON_VOL_DOWN 201#define LABEL_HELP "Hold Menu" 202#define LABEL_QUIT "Power" 203#define LABEL_MENU "Menu" 204#define LABEL_VOLUME "Volume +/-" 205 206#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 207#define VUMETER_QUIT BUTTON_POWER 208#define VUMETER_HELP BUTTON_VIEW 209#define VUMETER_MENU BUTTON_MENU 210#define VUMETER_UP BUTTON_UP 211#define VUMETER_DOWN BUTTON_DOWN 212#define LABEL_HELP "VIEW" 213#define LABEL_QUIT "POWER" 214#define LABEL_MENU "MENU" 215#define LABEL_VOLUME "UP/DOWN" 216 217#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 218#define VUMETER_QUIT BUTTON_POWER 219#define VUMETER_HELP BUTTON_NEXT 220#define VUMETER_MENU BUTTON_MENU 221#define VUMETER_UP BUTTON_UP 222#define VUMETER_DOWN BUTTON_DOWN 223#define LABEL_HELP "NEXT" 224#define LABEL_QUIT "QUIT" 225#define LABEL_MENU "MENU" 226#define LABEL_VOLUME "UP/DOWN" 227 228#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 229#define VUMETER_QUIT BUTTON_POWER 230#define VUMETER_HELP BUTTON_RIGHT 231#define VUMETER_MENU BUTTON_MENU 232#define VUMETER_UP BUTTON_UP 233#define VUMETER_DOWN BUTTON_DOWN 234#define LABEL_HELP "RIGHT" 235#define LABEL_QUIT "POWER" 236#define LABEL_MENU "MENU" 237#define LABEL_VOLUME "UP/DOWN" 238 239#elif CONFIG_KEYPAD == ONDAVX747_PAD 240#define VUMETER_QUIT BUTTON_POWER 241#define VUMETER_MENU BUTTON_MENU 242#define LABEL_QUIT "POWER" 243#define LABEL_MENU "MENU" 244 245#elif CONFIG_KEYPAD == ONDAVX777_PAD 246#define VUMETER_QUIT BUTTON_POWER 247#define LABEL_QUIT "POWER" 248 249#elif CONFIG_KEYPAD == MROBE500_PAD 250#define VUMETER_QUIT BUTTON_POWER 251#define LABEL_QUIT "POWER" 252 253#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ 254 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 255#define VUMETER_QUIT BUTTON_REW 256#define VUMETER_HELP BUTTON_PLAY 257#define VUMETER_MENU BUTTON_LEFT 258#define VUMETER_UP BUTTON_UP 259#define VUMETER_DOWN BUTTON_DOWN 260#define LABEL_HELP "PLAY" 261#define LABEL_QUIT "REW" 262#define LABEL_MENU "LEFT" 263#define LABEL_VOLUME "UP/DOWN" 264 265#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 266#define VUMETER_QUIT BUTTON_REC 267#define VUMETER_HELP BUTTON_PLAY 268#define VUMETER_MENU BUTTON_MENU 269#define VUMETER_UP BUTTON_UP 270#define VUMETER_DOWN BUTTON_DOWN 271#define LABEL_HELP "PLAY" 272#define LABEL_QUIT "REC" 273#define LABEL_MENU "MENU" 274#define LABEL_VOLUME "UP/DOWN" 275 276#elif CONFIG_KEYPAD == MPIO_HD200_PAD 277#define VUMETER_QUIT (BUTTON_REC|BUTTON_PLAY) 278#define VUMETER_HELP BUTTON_PLAY 279#define VUMETER_MENU BUTTON_FUNC 280#define VUMETER_UP BUTTON_VOL_UP 281#define VUMETER_DOWN BUTTON_VOL_DOWN 282#define LABEL_HELP "PLAY" 283#define LABEL_QUIT "REC+PLAY" 284#define LABEL_MENU "FUNC" 285#define LABEL_VOLUME "UP/DOWN" 286 287#elif CONFIG_KEYPAD == MPIO_HD300_PAD 288#define VUMETER_QUIT (BUTTON_MENU|BUTTON_REPEAT) 289#define VUMETER_HELP BUTTON_PLAY 290#define VUMETER_MENU BUTTON_MENU 291#define VUMETER_UP BUTTON_UP 292#define VUMETER_DOWN BUTTON_DOWN 293#define LABEL_HELP "PLAY" 294#define LABEL_QUIT "LONG MENU" 295#define LABEL_MENU "MENU" 296#define LABEL_VOLUME "UP/DOWN" 297 298#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 299#define VUMETER_QUIT BUTTON_BACK 300#define VUMETER_HELP BUTTON_PLAYPAUSE 301#define VUMETER_MENU (BUTTON_SELECT|BUTTON_REPEAT) 302#define VUMETER_UP BUTTON_VOL_UP 303#define VUMETER_DOWN BUTTON_VOL_DOWN 304#define LABEL_HELP "PLAY" 305#define LABEL_QUIT "BACK" 306#define LABEL_MENU "Long SELECT" 307#define LABEL_VOLUME "Vol+/Vol-" 308 309#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD 310#define VUMETER_QUIT BUTTON_POWER 311#define VUMETER_HELP BUTTON_NEXT 312#define VUMETER_MENU BUTTON_PREV 313#define VUMETER_UP BUTTON_UP 314#define VUMETER_DOWN BUTTON_DOWN 315#define LABEL_HELP "NEXT" 316#define LABEL_QUIT "POWER" 317#define LABEL_MENU "PREV" 318#define LABEL_VOLUME "VOL+/VOL-" 319 320#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) 321#define VUMETER_QUIT BUTTON_BACK 322#define VUMETER_HELP BUTTON_USER 323#define VUMETER_MENU BUTTON_MENU 324#define VUMETER_UP BUTTON_UP 325#define VUMETER_DOWN BUTTON_DOWN 326#define LABEL_HELP "User" 327#define LABEL_QUIT "Back" 328#define LABEL_MENU "Menu" 329#define LABEL_VOLUME "Up/Down" 330 331#elif (CONFIG_KEYPAD == HM60X_PAD) || \ 332 (CONFIG_KEYPAD == HM801_PAD) 333#define VUMETER_QUIT BUTTON_POWER 334#define VUMETER_HELP BUTTON_RIGHT 335#define VUMETER_MENU BUTTON_LEFT 336#define VUMETER_UP BUTTON_UP 337#define VUMETER_DOWN BUTTON_DOWN 338#define LABEL_HELP "RIGHT" 339#define LABEL_QUIT "POWER" 340#define LABEL_MENU "LEFT" 341#define LABEL_VOLUME "UP/DOWN" 342 343#elif CONFIG_KEYPAD == SONY_NWZ_PAD 344#define VUMETER_QUIT BUTTON_BACK 345#define VUMETER_HELP BUTTON_RIGHT 346#define VUMETER_MENU BUTTON_LEFT 347#define VUMETER_UP BUTTON_UP 348#define VUMETER_DOWN BUTTON_DOWN 349#define LABEL_HELP "Right" 350#define LABEL_QUIT "Back" 351#define LABEL_MENU "Left" 352#define LABEL_VOLUME "Up/Down" 353 354#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD 355#define VUMETER_QUIT BUTTON_BACK 356#define VUMETER_HELP BUTTON_SELECT 357#define VUMETER_MENU BUTTON_MENU 358#define VUMETER_UP BUTTON_UP 359#define VUMETER_DOWN BUTTON_DOWN 360#define LABEL_HELP "Select" 361#define LABEL_QUIT "Back" 362#define LABEL_MENU "Menu" 363#define LABEL_VOLUME "Up/Down" 364 365#elif CONFIG_KEYPAD == DX50_PAD 366#define VUMETER_QUIT (BUTTON_POWER|BUTTON_REL) 367#define VUMETER_MENU BUTTON_PLAY 368#define VUMETER_UP BUTTON_RIGHT 369#define VUMETER_DOWN BUTTON_LEFT 370#define LABEL_QUIT "Power" 371#define LABEL_MENU "Play" 372 373#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 374#define VUMETER_QUIT BUTTON_POWER 375#define VUMETER_MENU BUTTON_MENU 376#define LABEL_QUIT "Power" 377#define LABEL_MENU "Menu" 378 379#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 380#define VUMETER_QUIT (BUTTON_POWER|BUTTON_REL) 381#define VUMETER_MENU BUTTON_SELECT 382#define VUMETER_UP BUTTON_VOLUP 383#define VUMETER_DOWN BUTTON_VOLDOWN 384#define VUMETER_HELP BUTTON_UP 385#define LABEL_QUIT "Power" 386#define LABEL_MENU "Select" 387#define LABEL_HELP "Up" 388#define LABEL_VOLUME "Vol Up/Down" 389#define LABEL_MENU "Select" 390 391#elif (CONFIG_KEYPAD == XDUOO_X3_PAD) 392#define VUMETER_QUIT BUTTON_POWER 393#define VUMETER_HELP BUTTON_HOME 394#define VUMETER_MENU BUTTON_PLAY 395#define VUMETER_UP BUTTON_VOL_UP 396#define VUMETER_DOWN BUTTON_VOL_DOWN 397#define LABEL_HELP "HOME" 398#define LABEL_QUIT "POWER" 399#define LABEL_MENU "PLAY" 400#define LABEL_VOLUME "VOL UP/DN" 401 402#elif (CONFIG_KEYPAD == XDUOO_X3II_PAD) || (CONFIG_KEYPAD == XDUOO_X20_PAD) 403#define VUMETER_QUIT BUTTON_POWER 404#define VUMETER_HELP BUTTON_HOME 405#define VUMETER_MENU BUTTON_PLAY 406#define VUMETER_UP BUTTON_VOL_UP 407#define VUMETER_DOWN BUTTON_VOL_DOWN 408#define LABEL_HELP "HOME" 409#define LABEL_QUIT "POWER" 410#define LABEL_MENU "PLAY" 411#define LABEL_VOLUME "VOL UP/DN" 412 413#elif (CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD) 414#define VUMETER_QUIT BUTTON_POWER 415#define VUMETER_HELP BUTTON_HOME 416#define VUMETER_MENU BUTTON_PLAY 417#define VUMETER_UP BUTTON_VOL_UP 418#define VUMETER_DOWN BUTTON_VOL_DOWN 419#define LABEL_HELP "HOME" 420#define LABEL_QUIT "POWER" 421#define LABEL_MENU "PLAY" 422#define LABEL_VOLUME "VOL UP/DN" 423 424#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD) 425#define VUMETER_QUIT BUTTON_POWER 426#define VUMETER_HELP BUTTON_HOME 427#define VUMETER_MENU BUTTON_PLAY 428#define VUMETER_UP BUTTON_VOL_UP 429#define VUMETER_DOWN BUTTON_VOL_DOWN 430#define LABEL_HELP "HOME" 431#define LABEL_QUIT "POWER" 432#define LABEL_MENU "PLAY" 433#define LABEL_VOLUME "VOL UP/DN" 434 435#elif (CONFIG_KEYPAD == EROSQ_PAD) 436#define VUMETER_QUIT BUTTON_POWER 437#define VUMETER_HELP BUTTON_BACK 438#define VUMETER_MENU BUTTON_MENU 439#define VUMETER_UP BUTTON_VOL_UP 440#define VUMETER_DOWN BUTTON_VOL_DOWN 441#define LABEL_HELP "BACK" 442#define LABEL_QUIT "POWER" 443#define LABEL_MENU "MENU" 444#define LABEL_VOLUME "VOL UP/DN" 445 446#elif CONFIG_KEYPAD == FIIO_M3K_PAD 447#define VUMETER_QUIT BUTTON_POWER 448#define VUMETER_HELP BUTTON_BACK 449#define VUMETER_MENU BUTTON_MENU 450#define VUMETER_UP BUTTON_VOL_UP 451#define VUMETER_DOWN BUTTON_VOL_DOWN 452#define LABEL_HELP "BACK" 453#define LABEL_QUIT "POWER" 454#define LABEL_MENU "MENU" 455#define LABEL_VOLUME "VOL+/VOL-" 456 457#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 458/* use touchscreen */ 459 460#elif CONFIG_KEYPAD == SDL_PAD 461/* use touchscreen */ 462#elif CONFIG_KEYPAD == MA_PAD 463#define VUMETER_QUIT BUTTON_BACK 464#define VUMETER_HELP BUTTON_LEFT 465#define VUMETER_MENU BUTTON_MENU 466#define VUMETER_UP BUTTON_UP 467#define VUMETER_DOWN BUTTON_DOWN 468#define LABEL_HELP "LEFT" 469#define LABEL_QUIT "BACK" 470#define LABEL_MENU "MENU" 471#define LABEL_VOLUME "UP/DOWN" 472 473#elif CONFIG_KEYPAD == RG_NANO_PAD 474#define VUMETER_QUIT BUTTON_START 475#define VUMETER_HELP BUTTON_A 476#define VUMETER_MENU BUTTON_B 477#define VUMETER_UP BUTTON_UP 478#define VUMETER_DOWN BUTTON_DOWN 479#define LABEL_HELP "A" 480#define LABEL_QUIT "START" 481#define LABEL_MENU "B" 482#define LABEL_VOLUME "UP/DOWN" 483 484#else 485#error No keymap defined! 486#endif 487 488#ifdef HAVE_TOUCHSCREEN 489#ifndef VUMETER_QUIT 490#define VUMETER_QUIT BUTTON_TOPLEFT 491#define LABEL_QUIT "TOPLEFT" 492#endif 493#ifndef VUMETER_HELP 494#define VUMETER_HELP BUTTON_CENTER 495#define LABEL_HELP "CENTRE" 496#endif 497#ifndef VUMETER_MENU 498#define VUMETER_MENU BUTTON_TOPRIGHT 499#define LABEL_MENU "TOPRIGHT" 500#endif 501#ifndef VUMETER_UP 502#define VUMETER_UP BUTTON_TOPMIDDLE 503#endif 504#ifndef VUMETER_DOWN 505#define VUMETER_DOWN BUTTON_BOTTOMMIDDLE 506#endif 507#ifndef LABEL_VOLUME 508#define LABEL_VOLUME "UP/DOWN" 509#endif 510#endif 511 512/* Defines x positions on a logarithmic (dBfs) scale. */ 513unsigned char analog_db_scale[LCD_WIDTH/2]; 514 515/* Define's y positions, to make the needle arch, like a real needle would. */ 516unsigned char y_values[LCD_WIDTH/2]; 517 518const unsigned char digital_db_scale[] = 519{0,2,3,5,5,6,6,6,7,7,7,7,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10, 52010,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11}; 521 522const unsigned char needle_cover[] = 523{0x18, 0x1c, 0x1c, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1e, 0x1e, 0x1c, 0x1c, 0x18}; 524 525const unsigned char sound_speaker[] = {0x18,0x24,0x42,0xFF}; 526const unsigned char sound_low_level[] = {0x24,0x18}; 527const unsigned char sound_med_level[] = {0x42,0x3C}; 528const unsigned char sound_high_level[] = {0x81,0x7E}; 529const unsigned char sound_max_level[] = {0x0E,0xDF,0x0E}; 530 531const int half_width = LCD_WIDTH / 2; 532const int quarter_width = LCD_WIDTH / 4; 533const int half_height = LCD_HEIGHT / 2; 534 535/* approx ratio of the previous hard coded values */ 536const int analog_mini_1 = (LCD_WIDTH / 2)*0.1; 537const int analog_mini_2 = (LCD_WIDTH / 2)*0.25; 538const int analog_mini_3 = (LCD_WIDTH / 2)*0.4; 539const int analog_mini_4 = (LCD_WIDTH / 2)*0.75; 540 541const int digital_block_width = LCD_WIDTH / 11; 542const int digital_block_gap = (int)(LCD_WIDTH / 11) / 10; 543/* ammount to lead in on left so 11x blocks are centered - is often 0 */ 544const int digital_lead = (LCD_WIDTH - (((int)(LCD_WIDTH / 11))*11) ) / 2; 545 546const int digital_block_height = (LCD_HEIGHT - 54) / 2 ; 547 548#define ANALOG 0 /* The two meter types */ 549#define DIGITAL 1 550 551int left_needle_top_y; 552int left_needle_top_x; 553int last_left_needle_top_x; 554int right_needle_top_y; 555int right_needle_top_x; 556int last_right_needle_top_x = LCD_WIDTH / 2; 557 558int num_left_leds; 559int num_right_leds; 560int last_num_left_leds; 561int last_num_right_leds; 562 563int i; 564#ifdef HAVE_LCD_COLOR 565int screen_foreground; 566#endif 567 568#define MAX_PEAK 0x8000 569 570/* gap at the top for left/right etc */ 571#define NEEDLE_TOP SYSFONT_HEIGHT*3+1 572 573/* pow(M_E, 5) * 65536 */ 574#define E_POW_5 9726404 575 576struct saved_settings { 577 int meter_type; 578 bool analog_use_db_scale; 579 bool digital_use_db_scale; 580 bool analog_minimeters; 581 bool digital_minimeters; 582 int analog_decay; 583 int digital_decay; 584} vumeter_settings; 585 586static void reset_settings(void) { 587 vumeter_settings.meter_type=ANALOG; 588 vumeter_settings.analog_use_db_scale=true; 589 vumeter_settings.digital_use_db_scale=true; 590 vumeter_settings.analog_minimeters=true; 591 vumeter_settings.digital_minimeters=false; 592 vumeter_settings.analog_decay=3; 593 vumeter_settings.digital_decay=0; 594} 595 596static void calc_scales(void) 597{ 598 unsigned int fx_log_factor = E_POW_5/half_width; 599 unsigned int y,z; 600 601 long j; 602 long k; 603 int nh = LCD_HEIGHT - NEEDLE_TOP; 604 long nh2 = nh*nh; 605 606 for (i=1; i <= half_width; i++) 607 { 608 /* analog scale */ 609 y = (half_width/5)*fp16_log(i*fx_log_factor); 610 611 /* better way of checking for negative values? */ 612 z = y>>16; 613 if (z > LCD_WIDTH) 614 z = 0; 615 616 analog_db_scale[i-1] = z; 617 /* play nice */ 618 rb->yield(); 619 620 /* y values (analog needle co-ords) */ 621 j = i - (int)(half_width/2); 622 k = nh2 - ( j * j ); 623 624 /* fsqrt+1 seems to give a closer approximation */ 625 y_values[i-1] = LCD_HEIGHT - (fp_sqrt(k, 16)>>8) - 1; 626 rb->yield(); 627 } 628} 629 630static void load_settings(void) { 631 int fp = rb->open(PLUGIN_DEMOS_DATA_DIR "/.vu_meter", O_RDONLY); 632 if(fp>=0) { 633 rb->read(fp, &vumeter_settings, sizeof(struct saved_settings)); 634 rb->close(fp); 635 } 636 else { 637 reset_settings(); 638 rb->splash(HZ, "Press " LABEL_HELP " for help"); 639 } 640} 641 642static void save_settings(void) { 643 int fp = rb->creat(PLUGIN_DEMOS_DATA_DIR "/.vu_meter", 0666); 644 if(fp >= 0) { 645 rb->write (fp, &vumeter_settings, sizeof(struct saved_settings)); 646 rb->close(fp); 647 } 648} 649 650static void change_volume(int delta) { 651 int minvol = rb->sound_min(SOUND_VOLUME); 652 int maxvol = rb->sound_max(SOUND_VOLUME); 653 int vol = rb->global_status->volume + delta; 654 655 if (vol > maxvol) vol = maxvol; 656 else if (vol < minvol) vol = minvol; 657 if (vol != rb->global_status->volume) { 658 rb->sound_set(SOUND_VOLUME, vol); 659 rb->lcd_putsxyf(0,0, "%d", vol); 660 rb->lcd_update(); 661 rb->sleep(HZ/12); 662 } 663} 664 665static bool vu_meter_menu(void) 666{ 667 int selection; 668 bool menu_quit = false; 669 bool exit = false; 670 671 MENUITEM_STRINGLIST(menu,"VU Meter",NULL,"Meter Type","Scale", 672 "Minimeters","Decay Speed","Playback Control", 673 "Quit"); 674 675 static const struct opt_items meter_type_option[2] = { 676 { "Analog", -1 }, 677 { "Digital", -1 }, 678 }; 679 680 static const struct opt_items decay_speed_option[7] = { 681 { "No Decay", -1 }, 682 { "Very Fast", -1 }, 683 { "Fast", -1 }, 684 { "Medium", -1 }, 685 { "Medium-Slow", -1 }, 686 { "Slow", -1 }, 687 { "Very Slow", -1 }, 688 }; 689 690 while (!menu_quit) { 691 switch(rb->do_menu(&menu, &selection, NULL, false)) 692 { 693 case 0: 694 rb->set_option("Meter Type", &vumeter_settings.meter_type, RB_INT, 695 meter_type_option, 2, NULL); 696 break; 697 698 case 1: 699 if(vumeter_settings.meter_type==ANALOG) 700 { 701 rb->set_bool_options("Scale", &vumeter_settings.analog_use_db_scale, 702 "dBfs", -1, "Linear", -1, NULL); 703 } 704 else 705 { 706 rb->set_bool_options("Scale", &vumeter_settings.digital_use_db_scale, 707 "dBfs", -1, "Linear", -1, NULL); 708 } 709 break; 710 711 case 2: 712 if(vumeter_settings.meter_type==ANALOG) 713 { 714 rb->set_bool("Enable Minimeters", 715 &vumeter_settings.analog_minimeters); 716 } 717 else 718 { 719 rb->set_bool("Enable Minimeters", 720 &vumeter_settings.digital_minimeters); 721 } 722 break; 723 724 case 3: 725 if(vumeter_settings.meter_type==ANALOG) 726 { 727 rb->set_option("Decay Speed", &vumeter_settings.analog_decay, RB_INT, 728 decay_speed_option, 7, NULL); 729 } 730 else 731 { 732 rb->set_option("Decay Speed", &vumeter_settings.digital_decay, RB_INT, 733 decay_speed_option, 7, NULL); 734 } 735 break; 736 737 case 4: 738 playback_control(NULL); 739 break; 740 741 case 5: 742 exit = true; 743 /* fall through to exit the menu */ 744 default: 745 menu_quit = true; 746 break; 747 } 748 } 749 /* the menu uses the userfont, set it back to sysfont */ 750 rb->lcd_setfont(FONT_SYSFIXED); 751 return exit; 752} 753 754static void draw_analog_minimeters(void) { 755 rb->lcd_mono_bitmap(sound_speaker, quarter_width-28, SYSFONT_HEIGHT+4, 4, 8); 756 rb->lcd_set_drawmode(DRMODE_FG); 757 if(analog_mini_1<left_needle_top_x) 758 rb->lcd_mono_bitmap(sound_low_level, quarter_width-23, SYSFONT_HEIGHT+4, 2, 8); 759 if(analog_mini_2<left_needle_top_x) 760 rb->lcd_mono_bitmap(sound_med_level, quarter_width-21, SYSFONT_HEIGHT+4, 2, 8); 761 if(analog_mini_3<left_needle_top_x) 762 rb->lcd_mono_bitmap(sound_high_level, quarter_width-19, SYSFONT_HEIGHT+4, 2, 8); 763 if(analog_mini_4<left_needle_top_x) 764 rb->lcd_mono_bitmap(sound_max_level, quarter_width-16, SYSFONT_HEIGHT+4, 3, 8); 765 766 rb->lcd_set_drawmode(DRMODE_SOLID); 767 rb->lcd_mono_bitmap(sound_speaker, quarter_width+half_width-30, SYSFONT_HEIGHT+4, 4, 8); 768 rb->lcd_set_drawmode(DRMODE_FG); 769 if(analog_mini_1<(right_needle_top_x-half_width)) 770 rb->lcd_mono_bitmap(sound_low_level, quarter_width+half_width-25, SYSFONT_HEIGHT+4, 2, 8); 771 if(analog_mini_2<(right_needle_top_x-half_width)) 772 rb->lcd_mono_bitmap(sound_med_level, quarter_width+half_width-23, SYSFONT_HEIGHT+4, 2, 8); 773 if(analog_mini_3<(right_needle_top_x-half_width)) 774 rb->lcd_mono_bitmap(sound_high_level, quarter_width+half_width-21, SYSFONT_HEIGHT+4, 2, 8); 775 if(analog_mini_4<(right_needle_top_x-half_width)) 776 rb->lcd_mono_bitmap(sound_max_level, quarter_width+half_width-18, SYSFONT_HEIGHT+4, 3, 8); 777 rb->lcd_set_drawmode(DRMODE_SOLID); 778} 779 780static void draw_digital_minimeters(void) { 781#ifdef HAVE_LCD_COLOR 782 rb->lcd_set_foreground(LCD_RGBPACK(255, 255 - 23 * num_left_leds, 0)); 783#endif 784 rb->lcd_mono_bitmap(sound_speaker, 34, half_height-8, 4, 8); 785 rb->lcd_set_drawmode(DRMODE_FG); 786 if(1<num_left_leds) 787 rb->lcd_mono_bitmap(sound_low_level, 39, half_height-8, 2, 8); 788 if(2<num_left_leds) 789 rb->lcd_mono_bitmap(sound_med_level, 41, half_height-8, 2, 8); 790 if(5<num_left_leds) 791 rb->lcd_mono_bitmap(sound_high_level, 43, half_height-8, 2, 8); 792 if(8<num_left_leds) 793 rb->lcd_mono_bitmap(sound_max_level, 46, half_height-8, 3, 8); 794 795#ifdef HAVE_LCD_COLOR 796 rb->lcd_set_foreground(LCD_RGBPACK(255, 255 - 23 * num_right_leds, 0)); 797#endif 798 rb->lcd_set_drawmode(DRMODE_SOLID); 799 rb->lcd_mono_bitmap(sound_speaker, 34, half_height+8, 4, 8); 800 rb->lcd_set_drawmode(DRMODE_FG); 801 if(1<(num_right_leds)) 802 rb->lcd_mono_bitmap(sound_low_level, 39, half_height+8, 2, 8); 803 if(2<(num_right_leds)) 804 rb->lcd_mono_bitmap(sound_med_level, 41, half_height+8, 2, 8); 805 if(5<(num_right_leds)) 806 rb->lcd_mono_bitmap(sound_high_level, 43, half_height+8, 2, 8); 807 if(8<(num_right_leds)) 808 rb->lcd_mono_bitmap(sound_max_level, 46, half_height+8, 3, 8); 809 rb->lcd_set_drawmode(DRMODE_SOLID); 810 811#ifdef HAVE_LCD_COLOR 812 rb->lcd_set_foreground(screen_foreground); 813#endif 814} 815 816static void draw_analog_meter(uint32_t left_peak, uint32_t right_peak) 817{ 818 if(vumeter_settings.analog_use_db_scale) { 819 left_needle_top_x = analog_db_scale[left_peak * half_width / MAX_PEAK]; 820 right_needle_top_x = analog_db_scale[right_peak * half_width / MAX_PEAK] + half_width; 821 } 822 else { 823 left_needle_top_x = left_peak * half_width / MAX_PEAK; 824 right_needle_top_x = right_peak * half_width / MAX_PEAK + half_width; 825 } 826 827 /* Makes a decay on the needle */ 828 left_needle_top_x = (left_needle_top_x+last_left_needle_top_x*vumeter_settings.analog_decay) 829 /(vumeter_settings.analog_decay+1); 830 right_needle_top_x = (right_needle_top_x+last_right_needle_top_x*vumeter_settings.analog_decay) 831 /(vumeter_settings.analog_decay+1); 832 833 last_left_needle_top_x = left_needle_top_x; 834 last_right_needle_top_x = right_needle_top_x; 835 836 left_needle_top_y = y_values[left_needle_top_x]; 837 right_needle_top_y = y_values[right_needle_top_x-half_width]; 838 839 /* Needles */ 840 rb->lcd_drawline(quarter_width, LCD_HEIGHT-1, left_needle_top_x, left_needle_top_y); 841 rb->lcd_drawline((quarter_width+half_width), LCD_HEIGHT-1, right_needle_top_x, right_needle_top_y); 842 843 if(vumeter_settings.analog_minimeters) 844 draw_analog_minimeters(); 845 846 /* Needle covers */ 847 rb->lcd_set_drawmode(DRMODE_FG); 848 rb->lcd_mono_bitmap(needle_cover, quarter_width-6, LCD_HEIGHT-5, 13, 5); 849 rb->lcd_mono_bitmap(needle_cover, half_width+quarter_width-6, LCD_HEIGHT-5, 13, 5); 850 rb->lcd_set_drawmode(DRMODE_SOLID); 851 852 /* Show Left/Right */ 853 rb->lcd_putsxy(quarter_width-12, SYSFONT_HEIGHT+4, "Left"); 854 rb->lcd_putsxy(half_width+quarter_width-12, SYSFONT_HEIGHT+4, "Right"); 855 856 /* Line above/below the Left/Right text */ 857 rb->lcd_hline(0,LCD_WIDTH-1,SYSFONT_HEIGHT+1); 858 rb->lcd_hline(0,LCD_WIDTH-1,SYSFONT_HEIGHT*2+5); 859 860 for(i=0; i<half_width; i++) { 861 rb->lcd_drawpixel(i, (y_values[i])-2); 862 rb->lcd_drawpixel(i+half_width, (y_values[i])-2); 863 } 864} 865 866static void draw_digital_meter(uint32_t left_peak, uint32_t right_peak) 867{ 868 if(vumeter_settings.digital_use_db_scale) { 869 num_left_leds = digital_db_scale[left_peak * 44 / MAX_PEAK]; 870 num_right_leds = digital_db_scale[right_peak * 44 / MAX_PEAK]; 871 } 872 else { 873 num_left_leds = left_peak * 11 / MAX_PEAK; 874 num_right_leds = right_peak * 11 / MAX_PEAK; 875 } 876 877 num_left_leds = (num_left_leds+last_num_left_leds*vumeter_settings.digital_decay) 878 /(vumeter_settings.digital_decay+1); 879 num_right_leds = (num_right_leds+last_num_right_leds*vumeter_settings.digital_decay) 880 /(vumeter_settings.digital_decay+1); 881 882 last_num_left_leds = num_left_leds; 883 last_num_right_leds = num_right_leds; 884 885 rb->lcd_set_drawmode(DRMODE_FG); 886 /* LEDS */ 887 for(i=0; i<num_left_leds; i++) { 888#ifdef HAVE_LCD_COLOR 889 rb->lcd_set_foreground(LCD_RGBPACK(255, 255 - 23 * i, 0)); 890#endif 891 rb->lcd_fillrect((digital_lead + (i*digital_block_width)), 892 14, digital_block_width - digital_block_gap, digital_block_height); 893 } 894 895 for(i=0; i<num_right_leds; i++) { 896#ifdef HAVE_LCD_COLOR 897 rb->lcd_set_foreground(LCD_RGBPACK(255, 255 - 23 * i, 0)); 898#endif 899 rb->lcd_fillrect((digital_lead + (i*digital_block_width)), 900 (half_height + 20), digital_block_width - digital_block_gap, 901 digital_block_height); 902 } 903 904#ifdef HAVE_LCD_COLOR 905 rb->lcd_set_foreground(screen_foreground); 906#endif 907 rb->lcd_set_drawmode(DRMODE_SOLID); 908 909 if(vumeter_settings.digital_minimeters) 910 draw_digital_minimeters(); 911 912 /* Lines above/below where the LEDS are */ 913 rb->lcd_hline(0,LCD_WIDTH-1,12); 914 rb->lcd_hline(0,LCD_WIDTH-1,half_height-12); 915 916 rb->lcd_hline(0,LCD_WIDTH-1,half_height+18); 917 rb->lcd_hline(0,LCD_WIDTH-1,LCD_HEIGHT-6); 918 919 /* Show Left/Right */ 920 rb->lcd_putsxy(2, half_height-8, "Left"); 921 rb->lcd_putsxy(2, half_height+8, "Right"); 922 923 /* Line in the middle */ 924 rb->lcd_hline(0,LCD_WIDTH-1,half_height+3); 925} 926 927static void draw_title(void) 928{ 929 static unsigned int sampr; 930 static int x; 931 static char title[16]; 932 933 if (sampr != rb->mixer_get_frequency()) 934 { 935 sampr = rb->mixer_get_frequency(); 936 if ((sampr % 1000) < 100) 937 rb->snprintf(title, sizeof title, "VU %d kHz", 938 sampr / 1000); 939 else 940 rb->snprintf(title, sizeof title, "VU %d.%u kHz", 941 sampr / 1000, (sampr % 1000) / 100); 942 943 rb->font_getstringsize(title, &x, NULL, FONT_SYSFIXED); 944 x = half_width - (x/2); /* centered */ 945 } 946 rb->lcd_putsxy(x, 0, title); 947} 948 949static void vu_meter_cleanup(void) 950{ 951 /* Turn on backlight timeout (revert to settings) */ 952 backlight_use_settings(); 953} 954 955enum plugin_status plugin_start(const void* parameter) 956{ 957 static struct pcm_peaks peaks; 958 int button; 959#if defined(VUMETER_HELP_PRE) || defined(VUMETER_MENU_PRE) 960 int lastbutton = BUTTON_NONE; 961#endif 962 963 (void) parameter; 964 965 calc_scales(); 966 967 atexit(vu_meter_cleanup); 968 969 load_settings(); 970 rb->lcd_setfont(FONT_SYSFIXED); 971#ifdef HAVE_LCD_COLOR 972 screen_foreground = rb->lcd_get_foreground(); 973#endif 974 975 /* Turn off backlight timeout */ 976 backlight_ignore_timeout(); 977 978 while (1) 979 { 980 rb->lcd_clear_display(); 981 982 draw_title(); 983 984#ifdef USB_ENABLE_AUDIO 985 if (rb->usb_audio_get_playing()) 986 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_USBAUDIO, 987 &peaks); 988 else 989#endif 990 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK, 991 &peaks); 992 993 if(vumeter_settings.meter_type == ANALOG) 994 draw_analog_meter(peaks.left, peaks.right); 995 else 996 draw_digital_meter(peaks.left, peaks.right); 997 998 rb->lcd_update(); 999 1000 button = rb->button_get_w_tmo(1); 1001 switch (button) 1002 { 1003#ifdef VUMETER_RC_QUIT 1004 case VUMETER_RC_QUIT: 1005#endif 1006 case VUMETER_QUIT: 1007 save_settings(); 1008 return PLUGIN_OK; 1009 break; 1010 1011 case VUMETER_HELP: 1012#ifdef VUMETER_HELP_PRE 1013 if (lastbutton != VUMETER_HELP_PRE) 1014 break; 1015#endif 1016 rb->lcd_clear_display(); 1017 rb->lcd_puts(0, 0, LABEL_QUIT ": Exit"); 1018 rb->lcd_puts(0, 1, LABEL_MENU ": Settings"); 1019 rb->lcd_puts(0, 2, LABEL_VOLUME ": Volume"); 1020 rb->lcd_update(); 1021 rb->sleep(HZ*3); 1022 break; 1023 1024 case VUMETER_MENU: 1025 1026#ifdef VUMETER_MENU2 1027 case VUMETER_MENU2: 1028#endif 1029 1030#ifdef VUMETER_MENU_PRE 1031 if (lastbutton != VUMETER_MENU_PRE) 1032 break; 1033#endif 1034 if(vu_meter_menu()) 1035 return PLUGIN_OK; 1036 break; 1037 1038 case VUMETER_UP: 1039 case VUMETER_UP | BUTTON_REPEAT: 1040 change_volume(1); 1041 break; 1042 1043 case VUMETER_DOWN: 1044 case VUMETER_DOWN | BUTTON_REPEAT: 1045 change_volume(-1); 1046 break; 1047 1048 default: 1049 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) 1050 return PLUGIN_USB_CONNECTED; 1051 break; 1052 } 1053#if defined(VUMETER_HELP_PRE) || defined(VUMETER_MENU_PRE) 1054 if (button != BUTTON_NONE) 1055 lastbutton = button; 1056#endif 1057 } 1058}