A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1472 lines 47 kB view raw
1#include "plugin.h" 2#include "lib/helper.h" 3#include "lib/configfile.h" 4 5#include "mpegplayer.h" 6#include "mpeg_settings.h" 7 8struct mpeg_settings settings; 9 10#define THUMB_DELAY (75*HZ/100) 11 12/* button definitions */ 13#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 14 (CONFIG_KEYPAD == IRIVER_H300_PAD) 15#define MPEG_START_TIME_SELECT BUTTON_ON 16#define MPEG_START_TIME_LEFT BUTTON_LEFT 17#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 18#define MPEG_START_TIME_UP BUTTON_UP 19#define MPEG_START_TIME_DOWN BUTTON_DOWN 20#define MPEG_START_TIME_EXIT BUTTON_OFF 21 22#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) 23#define MPEG_START_TIME_SELECT BUTTON_PLAY 24#define MPEG_START_TIME_LEFT BUTTON_LEFT 25#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 26#define MPEG_START_TIME_UP BUTTON_UP 27#define MPEG_START_TIME_DOWN BUTTON_DOWN 28#define MPEG_START_TIME_EXIT BUTTON_POWER 29 30#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 31 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 32 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 33#define MPEG_START_TIME_SELECT BUTTON_SELECT 34#define MPEG_START_TIME_LEFT BUTTON_LEFT 35#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 36#define MPEG_START_TIME_UP BUTTON_SCROLL_FWD 37#define MPEG_START_TIME_DOWN BUTTON_SCROLL_BACK 38#define MPEG_START_TIME_EXIT BUTTON_MENU 39 40#elif CONFIG_KEYPAD == GIGABEAT_PAD 41#define MPEG_START_TIME_SELECT BUTTON_SELECT 42#define MPEG_START_TIME_LEFT BUTTON_LEFT 43#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 44#define MPEG_START_TIME_UP BUTTON_UP 45#define MPEG_START_TIME_DOWN BUTTON_DOWN 46#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 47#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 48#define MPEG_START_TIME_EXIT BUTTON_POWER 49 50#define MPEG_START_TIME_RC_SELECT (BUTTON_RC_PLAY | BUTTON_REL) 51#define MPEG_START_TIME_RC_LEFT BUTTON_RC_REW 52#define MPEG_START_TIME_RC_RIGHT BUTTON_RC_FF 53#define MPEG_START_TIME_RC_UP BUTTON_RC_VOL_UP 54#define MPEG_START_TIME_RC_DOWN BUTTON_RC_VOL_DOWN 55#define MPEG_START_TIME_RC_EXIT (BUTTON_RC_PLAY | BUTTON_REPEAT) 56 57#elif CONFIG_KEYPAD == GIGABEAT_S_PAD 58#define MPEG_START_TIME_SELECT BUTTON_SELECT 59#define MPEG_START_TIME_LEFT BUTTON_LEFT 60#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 61#define MPEG_START_TIME_UP BUTTON_UP 62#define MPEG_START_TIME_DOWN BUTTON_DOWN 63#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 64#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 65#define MPEG_START_TIME_EXIT BUTTON_POWER 66 67#define MPEG_START_TIME_RC_SELECT (BUTTON_RC_PLAY | BUTTON_REL) 68#define MPEG_START_TIME_RC_LEFT BUTTON_RC_REW 69#define MPEG_START_TIME_RC_RIGHT BUTTON_RC_FF 70#define MPEG_START_TIME_RC_UP BUTTON_RC_VOL_UP 71#define MPEG_START_TIME_RC_DOWN BUTTON_RC_VOL_DOWN 72#define MPEG_START_TIME_RC_EXIT (BUTTON_RC_PLAY | BUTTON_REPEAT) 73 74#elif CONFIG_KEYPAD == IRIVER_H10_PAD 75#define MPEG_START_TIME_SELECT BUTTON_PLAY 76#define MPEG_START_TIME_LEFT BUTTON_LEFT 77#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 78#define MPEG_START_TIME_UP BUTTON_SCROLL_UP 79#define MPEG_START_TIME_DOWN BUTTON_SCROLL_DOWN 80#define MPEG_START_TIME_EXIT BUTTON_POWER 81 82#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 83#define MPEG_START_TIME_SELECT BUTTON_SELECT 84#define MPEG_START_TIME_LEFT BUTTON_LEFT 85#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 86#define MPEG_START_TIME_UP BUTTON_UP 87#define MPEG_START_TIME_DOWN BUTTON_DOWN 88#define MPEG_START_TIME_LEFT2 BUTTON_SCROLL_BACK 89#define MPEG_START_TIME_RIGHT2 BUTTON_SCROLL_FWD 90#define MPEG_START_TIME_EXIT BUTTON_POWER 91 92#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 93#define MPEG_START_TIME_SELECT BUTTON_SELECT 94#define MPEG_START_TIME_LEFT BUTTON_LEFT 95#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 96#define MPEG_START_TIME_UP BUTTON_UP 97#define MPEG_START_TIME_DOWN BUTTON_DOWN 98#define MPEG_START_TIME_LEFT2 BUTTON_SCROLL_BACK 99#define MPEG_START_TIME_RIGHT2 BUTTON_SCROLL_FWD 100#define MPEG_START_TIME_EXIT (BUTTON_HOME|BUTTON_REPEAT) 101 102#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \ 103(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \ 104(CONFIG_KEYPAD == SANSA_M200_PAD) 105#define MPEG_START_TIME_SELECT BUTTON_SELECT 106#define MPEG_START_TIME_LEFT BUTTON_LEFT 107#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 108#define MPEG_START_TIME_UP BUTTON_UP 109#define MPEG_START_TIME_DOWN BUTTON_DOWN 110#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 111#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 112#define MPEG_START_TIME_EXIT BUTTON_POWER 113 114#elif CONFIG_KEYPAD == MROBE500_PAD 115#define MPEG_START_TIME_SELECT BUTTON_RC_HEART 116#define MPEG_START_TIME_LEFT BUTTON_LEFT 117#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 118#define MPEG_START_TIME_UP BUTTON_RC_PLAY 119#define MPEG_START_TIME_DOWN BUTTON_RC_DOWN 120#define MPEG_START_TIME_LEFT2 BUTTON_RC_VOL_UP 121#define MPEG_START_TIME_RIGHT2 BUTTON_RC_VOL_DOWN 122#define MPEG_START_TIME_EXIT BUTTON_POWER 123 124#elif CONFIG_KEYPAD == MROBE100_PAD 125#define MPEG_START_TIME_SELECT BUTTON_SELECT 126#define MPEG_START_TIME_LEFT BUTTON_LEFT 127#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 128#define MPEG_START_TIME_UP BUTTON_UP 129#define MPEG_START_TIME_DOWN BUTTON_DOWN 130#define MPEG_START_TIME_LEFT2 BUTTON_PLAY 131#define MPEG_START_TIME_RIGHT2 BUTTON_MENU 132#define MPEG_START_TIME_EXIT BUTTON_POWER 133 134#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 135#define MPEG_START_TIME_SELECT BUTTON_RC_PLAY 136#define MPEG_START_TIME_LEFT BUTTON_RC_REW 137#define MPEG_START_TIME_RIGHT BUTTON_RC_FF 138#define MPEG_START_TIME_UP BUTTON_RC_VOL_UP 139#define MPEG_START_TIME_DOWN BUTTON_RC_VOL_DOWN 140#define MPEG_START_TIME_EXIT BUTTON_RC_REC 141 142#elif CONFIG_KEYPAD == COWON_D2_PAD 143#define MPEG_START_TIME_EXIT BUTTON_POWER 144 145#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 146#define MPEG_START_TIME_SELECT BUTTON_SELECT 147#define MPEG_START_TIME_LEFT BUTTON_LEFT 148#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 149#define MPEG_START_TIME_UP BUTTON_UP 150#define MPEG_START_TIME_DOWN BUTTON_DOWN 151#define MPEG_START_TIME_LEFT2 BUTTON_PLAY 152#define MPEG_START_TIME_RIGHT2 BUTTON_MENU 153#define MPEG_START_TIME_EXIT BUTTON_BACK 154 155#elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) 156#define MPEG_START_TIME_SELECT (BUTTON_PLAY|BUTTON_REL) 157#define MPEG_START_TIME_LEFT BUTTON_BACK 158#define MPEG_START_TIME_RIGHT BUTTON_MENU 159#define MPEG_START_TIME_UP BUTTON_UP 160#define MPEG_START_TIME_DOWN BUTTON_DOWN 161#define MPEG_START_TIME_EXIT (BUTTON_PLAY|BUTTON_REPEAT) 162 163#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 164#define MPEG_START_TIME_SELECT BUTTON_SELECT 165#define MPEG_START_TIME_LEFT BUTTON_LEFT 166#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 167#define MPEG_START_TIME_UP BUTTON_UP 168#define MPEG_START_TIME_DOWN BUTTON_DOWN 169#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 170#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 171#define MPEG_START_TIME_EXIT BUTTON_POWER 172 173#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 174#define MPEG_START_TIME_SELECT BUTTON_PLAY 175#define MPEG_START_TIME_LEFT BUTTON_LEFT 176#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 177#define MPEG_START_TIME_UP BUTTON_UP 178#define MPEG_START_TIME_DOWN BUTTON_DOWN 179#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 180#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 181#define MPEG_START_TIME_EXIT BUTTON_POWER 182 183#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 184#define MPEG_START_TIME_SELECT BUTTON_PLAY 185#define MPEG_START_TIME_LEFT BUTTON_PREV 186#define MPEG_START_TIME_RIGHT BUTTON_NEXT 187#define MPEG_START_TIME_UP BUTTON_UP 188#define MPEG_START_TIME_DOWN BUTTON_DOWN 189#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 190#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 191#define MPEG_START_TIME_EXIT BUTTON_POWER 192 193#elif CONFIG_KEYPAD == ONDAVX747_PAD 194#define MPEG_START_TIME_EXIT BUTTON_POWER 195 196#elif CONFIG_KEYPAD == ONDAVX777_PAD 197#define MPEG_START_TIME_EXIT BUTTON_POWER 198 199#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ 200 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 201#define MPEG_START_TIME_SELECT BUTTON_PLAY 202#define MPEG_START_TIME_LEFT BUTTON_LEFT 203#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 204#define MPEG_START_TIME_UP BUTTON_UP 205#define MPEG_START_TIME_DOWN BUTTON_DOWN 206#define MPEG_START_TIME_EXIT BUTTON_REW 207 208#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 209#define MPEG_START_TIME_SELECT BUTTON_PLAY 210#define MPEG_START_TIME_LEFT BUTTON_PREV 211#define MPEG_START_TIME_RIGHT BUTTON_NEXT 212#define MPEG_START_TIME_UP BUTTON_UP 213#define MPEG_START_TIME_DOWN BUTTON_DOWN 214#define MPEG_START_TIME_LEFT2 BUTTON_OK 215#define MPEG_START_TIME_RIGHT2 BUTTON_CANCEL 216#define MPEG_START_TIME_EXIT BUTTON_REC 217 218#elif CONFIG_KEYPAD == MPIO_HD200_PAD 219#define MPEG_START_TIME_SELECT BUTTON_FUNC 220#define MPEG_START_TIME_LEFT BUTTON_REW 221#define MPEG_START_TIME_RIGHT BUTTON_FF 222#define MPEG_START_TIME_UP BUTTON_VOL_UP 223#define MPEG_START_TIME_DOWN BUTTON_VOL_DOWN 224#define MPEG_START_TIME_EXIT BUTTON_REC 225 226#elif CONFIG_KEYPAD == MPIO_HD300_PAD 227#define MPEG_START_TIME_SELECT BUTTON_ENTER 228#define MPEG_START_TIME_LEFT BUTTON_REW 229#define MPEG_START_TIME_RIGHT BUTTON_FF 230#define MPEG_START_TIME_UP BUTTON_UP 231#define MPEG_START_TIME_DOWN BUTTON_DOWN 232#define MPEG_START_TIME_EXIT BUTTON_REC 233 234#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 235#define MPEG_START_TIME_SELECT BUTTON_SELECT 236#define MPEG_START_TIME_LEFT BUTTON_LEFT 237#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 238#define MPEG_START_TIME_UP BUTTON_UP 239#define MPEG_START_TIME_DOWN BUTTON_DOWN 240#define MPEG_START_TIME_EXIT BUTTON_POWER 241 242#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD 243#define MPEG_START_TIME_SELECT BUTTON_SELECT 244#define MPEG_START_TIME_LEFT BUTTON_LEFT 245#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 246#define MPEG_START_TIME_UP BUTTON_UP 247#define MPEG_START_TIME_DOWN BUTTON_DOWN 248#define MPEG_START_TIME_EXIT BUTTON_POWER 249 250#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD 251#define MPEG_START_TIME_SELECT BUTTON_SELECT 252#define MPEG_START_TIME_LEFT BUTTON_LEFT 253#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 254#define MPEG_START_TIME_UP BUTTON_UP 255#define MPEG_START_TIME_DOWN BUTTON_DOWN 256#define MPEG_START_TIME_EXIT BUTTON_BACK 257 258#elif (CONFIG_KEYPAD == HM60X_PAD) || (CONFIG_KEYPAD == HM801_PAD) 259#define MPEG_START_TIME_SELECT BUTTON_SELECT 260#define MPEG_START_TIME_LEFT BUTTON_LEFT 261#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 262#define MPEG_START_TIME_UP BUTTON_UP 263#define MPEG_START_TIME_DOWN BUTTON_DOWN 264#define MPEG_START_TIME_EXIT BUTTON_POWER 265 266#elif CONFIG_KEYPAD == SONY_NWZ_PAD 267#define MPEG_START_TIME_SELECT BUTTON_PLAY 268#define MPEG_START_TIME_LEFT BUTTON_LEFT 269#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 270#define MPEG_START_TIME_UP BUTTON_UP 271#define MPEG_START_TIME_DOWN BUTTON_DOWN 272#define MPEG_START_TIME_EXIT BUTTON_BACK 273 274#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD 275#define MPEG_START_TIME_SELECT BUTTON_SELECT 276#define MPEG_START_TIME_LEFT BUTTON_LEFT 277#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 278#define MPEG_START_TIME_UP BUTTON_UP 279#define MPEG_START_TIME_DOWN BUTTON_DOWN 280#define MPEG_START_TIME_EXIT BUTTON_BACK 281 282#elif CONFIG_KEYPAD == DX50_PAD 283#define MPEG_START_TIME_EXIT BUTTON_POWER 284#define MPEG_START_TIME_SELECT BUTTON_PLAY 285#define MPEG_START_TIME_LEFT BUTTON_LEFT 286#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 287#define MPEG_START_TIME_UP BUTTON_VOL_UP 288#define MPEG_START_TIME_DOWN BUTTON_VOL_DOWN 289 290#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 291#define MPEG_START_TIME_EXIT BUTTON_POWER 292 293#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 294#define MPEG_START_TIME_SELECT BUTTON_SELECT 295#define MPEG_START_TIME_LEFT BUTTON_LEFT 296#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 297#define MPEG_START_TIME_UP BUTTON_UP 298#define MPEG_START_TIME_DOWN BUTTON_DOWN 299#define MPEG_START_TIME_EXIT BUTTON_POWER 300 301#elif CONFIG_KEYPAD == XDUOO_X3_PAD 302#define MPEG_START_TIME_SELECT BUTTON_PLAY 303#define MPEG_START_TIME_LEFT BUTTON_PREV 304#define MPEG_START_TIME_RIGHT BUTTON_NEXT 305#define MPEG_START_TIME_UP BUTTON_HOME 306#define MPEG_START_TIME_DOWN BUTTON_OPTION 307#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 308#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 309#define MPEG_START_TIME_EXIT BUTTON_POWER 310 311#elif CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD 312#define MPEG_START_TIME_SELECT BUTTON_PLAY 313#define MPEG_START_TIME_LEFT BUTTON_PREV 314#define MPEG_START_TIME_RIGHT BUTTON_NEXT 315#define MPEG_START_TIME_UP BUTTON_HOME 316#define MPEG_START_TIME_DOWN BUTTON_OPTION 317#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 318#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 319#define MPEG_START_TIME_EXIT BUTTON_POWER 320 321#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD 322#define MPEG_START_TIME_SELECT BUTTON_PLAY 323#define MPEG_START_TIME_LEFT BUTTON_PREV 324#define MPEG_START_TIME_RIGHT BUTTON_NEXT 325#define MPEG_START_TIME_UP BUTTON_HOME 326#define MPEG_START_TIME_DOWN BUTTON_OPTION 327#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP 328#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN 329#define MPEG_START_TIME_EXIT BUTTON_POWER 330 331#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD 332#define MPEG_START_TIME_SELECT BUTTON_PLAY 333#define MPEG_START_TIME_LEFT BUTTON_HOME 334#define MPEG_START_TIME_RIGHT BUTTON_VOL_DOWN 335#define MPEG_START_TIME_UP BUTTON_PREV 336#define MPEG_START_TIME_DOWN BUTTON_NEXT 337#define MPEG_START_TIME_LEFT2 (BUTTON_POWER + BUTTON_HOME) 338#define MPEG_START_TIME_RIGHT2 (BUTTON_POWER + BUTTON_VOL_DOWN) 339#define MPEG_START_TIME_EXIT BUTTON_POWER 340 341#elif CONFIG_KEYPAD == EROSQ_PAD 342#define MPEG_START_TIME_SELECT BUTTON_PLAY 343#define MPEG_START_TIME_LEFT BUTTON_SCROLL_BACK 344#define MPEG_START_TIME_RIGHT BUTTON_SCROLL_FWD 345#define MPEG_START_TIME_UP BUTTON_PREV 346#define MPEG_START_TIME_DOWN BUTTON_NEXT 347#define MPEG_START_TIME_EXIT BUTTON_POWER 348 349#elif CONFIG_KEYPAD == FIIO_M3K_PAD 350#define MPEG_START_TIME_SELECT BUTTON_SELECT 351#define MPEG_START_TIME_LEFT BUTTON_LEFT 352#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 353#define MPEG_START_TIME_UP BUTTON_UP 354#define MPEG_START_TIME_DOWN BUTTON_DOWN 355#define MPEG_START_TIME_EXIT BUTTON_POWER 356 357#elif CONFIG_KEYPAD == MA_PAD 358#define MPEG_START_TIME_SELECT BUTTON_PLAY 359#define MPEG_START_TIME_LEFT BUTTON_LEFT 360#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 361#define MPEG_START_TIME_UP BUTTON_UP 362#define MPEG_START_TIME_DOWN BUTTON_DOWN 363#define MPEG_START_TIME_EXIT BUTTON_BACK 364 365#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 366#define MPEG_START_TIME_EXIT BUTTON_POWER 367 368#elif CONFIG_KEYPAD == RG_NANO_PAD 369#define MPEG_START_TIME_SELECT BUTTON_A 370#define MPEG_START_TIME_LEFT BUTTON_LEFT 371#define MPEG_START_TIME_RIGHT BUTTON_RIGHT 372#define MPEG_START_TIME_LEFT2 BUTTON_L 373#define MPEG_START_TIME_RIGHT2 BUTTON_R 374#define MPEG_START_TIME_UP BUTTON_UP 375#define MPEG_START_TIME_DOWN BUTTON_DOWN 376#define MPEG_START_TIME_EXIT BUTTON_START 377 378#else 379#error No keymap defined! 380#endif 381 382#ifdef HAVE_TOUCHSCREEN 383#ifndef MPEG_START_TIME_SELECT 384#define MPEG_START_TIME_SELECT BUTTON_CENTER 385#endif 386#ifndef MPEG_START_TIME_LEFT 387#define MPEG_START_TIME_LEFT BUTTON_MIDLEFT 388#endif 389#ifndef MPEG_START_TIME_RIGHT 390#define MPEG_START_TIME_RIGHT BUTTON_MIDRIGHT 391#endif 392#ifndef MPEG_START_TIME_UP 393#define MPEG_START_TIME_UP BUTTON_TOPMIDDLE 394#endif 395#ifndef MPEG_START_TIME_DOWN 396#define MPEG_START_TIME_DOWN BUTTON_BOTTOMMIDDLE 397#endif 398#ifndef MPEG_START_TIME_LEFT2 399#define MPEG_START_TIME_LEFT2 BUTTON_TOPRIGHT 400#endif 401#ifndef MPEG_START_TIME_RIGHT2 402#define MPEG_START_TIME_RIGHT2 BUTTON_TOPLEFT 403#endif 404#ifndef MPEG_START_TIME_EXIT 405#define MPEG_START_TIME_EXIT BUTTON_TOPLEFT 406#endif 407#endif 408 409static struct configdata config[] = 410{ 411 {TYPE_INT, 0, 2, { .int_p = &settings.showfps }, "Show FPS", NULL}, 412 {TYPE_INT, 0, 2, { .int_p = &settings.limitfps }, "Limit FPS", NULL}, 413 {TYPE_INT, 0, 2, { .int_p = &settings.skipframes }, "Skip frames", NULL}, 414 {TYPE_INT, 0, INT_MAX, { .int_p = &settings.resume_count }, "Resume count", 415 NULL}, 416 {TYPE_INT, 0, MPEG_RESUME_NUM_OPTIONS, 417 { .int_p = &settings.resume_options }, "Resume options", NULL}, 418#if MPEG_OPTION_DITHERING_ENABLED 419 {TYPE_INT, 0, INT_MAX, { .int_p = &settings.displayoptions }, 420 "Display options", NULL}, 421#endif 422 {TYPE_INT, 0, 2, { .int_p = &settings.tone_controls }, "Tone controls", 423 NULL}, 424 {TYPE_INT, 0, 2, { .int_p = &settings.channel_modes }, "Channel modes", 425 NULL}, 426 {TYPE_INT, 0, 2, { .int_p = &settings.crossfeed }, "Crossfeed", NULL}, 427 {TYPE_INT, 0, 2, { .int_p = &settings.equalizer }, "Equalizer", NULL}, 428 {TYPE_INT, 0, 2, { .int_p = &settings.dithering }, "Dithering", NULL}, 429 {TYPE_INT, 0, 2, { .int_p = &settings.play_mode }, "Play mode", NULL}, 430#ifdef HAVE_BACKLIGHT_BRIGHTNESS 431 {TYPE_INT, -1, INT_MAX, { .int_p = &settings.backlight_brightness }, 432 "Backlight brightness", NULL}, 433#endif 434}; 435 436static const struct opt_items noyes[2] = { 437 { STR(LANG_SET_BOOL_NO) }, 438 { STR(LANG_SET_BOOL_YES) }, 439}; 440 441static const struct opt_items singleall[2] = { 442 { STR(LANG_SINGLE) }, 443 { STR(LANG_ALL) }, 444}; 445 446static const struct opt_items globaloff[2] = { 447 { STR(LANG_OFF) }, 448 { STR(LANG_USE_SOUND_SETTING) }, 449}; 450 451static void mpeg_settings(void); 452static bool mpeg_set_option(const char* string, 453 void* variable, 454 enum optiontype type, 455 const struct opt_items* options, 456 int numoptions, 457 void (*function)(int)) 458{ 459 mpeg_sysevent_clear(); 460 461 /* This eats SYS_POWEROFF - :\ */ 462 bool usb = rb->set_option(string, variable, type, options, numoptions, 463 function); 464 465 if (usb) 466 mpeg_sysevent_set(); 467 468 return usb; 469} 470 471#ifdef HAVE_BACKLIGHT_BRIGHTNESS /* Only used for this atm */ 472static bool mpeg_set_int(const char *string, const char *unit, 473 int voice_unit, const int *variable, 474 void (*function)(int), int step, 475 int min, 476 int max, 477 const char* (*formatter)(char*, size_t, int, const char*), 478 int32_t (*get_talk_id)(int, int)) 479{ 480 mpeg_sysevent_clear(); 481 482 bool usb = rb->set_int_ex(string, unit, voice_unit, variable, function, 483 step, min, max, formatter, get_talk_id); 484 485 if (usb) 486 mpeg_sysevent_set(); 487 488 return usb; 489} 490 491static int32_t backlight_brightness_getlang(int value, int unit) 492{ 493 if (value < 0) 494 return LANG_USE_COMMON_SETTING; 495 496 return TALK_ID(value + MIN_BRIGHTNESS_SETTING, unit); 497} 498 499void mpeg_backlight_update_brightness(int value) 500{ 501 if (value >= 0) 502 { 503 value += MIN_BRIGHTNESS_SETTING; 504 backlight_brightness_set(value); 505 } 506 else 507 { 508 backlight_brightness_use_setting(); 509 } 510} 511 512static void backlight_brightness_function(int value) 513{ 514 mpeg_backlight_update_brightness(value); 515} 516 517static const char* backlight_brightness_formatter(char *buf, size_t length, 518 int value, const char *input) 519{ 520 (void)input; 521 522 if (value < 0) 523 return rb->str(LANG_USE_COMMON_SETTING); 524 else 525 rb->snprintf(buf, length, "%d", value + MIN_BRIGHTNESS_SETTING); 526 return buf; 527} 528#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ 529 530/* Sync a particular audio setting to global or mpegplayer forced off */ 531static void sync_audio_setting(int setting, bool global) 532{ 533 switch (setting) 534 { 535 case MPEG_AUDIO_TONE_CONTROLS: 536 #ifdef AUDIOHW_HAVE_BASS 537 rb->sound_set(SOUND_BASS, (global || settings.tone_controls) 538 ? rb->global_settings->bass 539 : rb->sound_default(SOUND_BASS)); 540 #endif 541 #ifdef AUDIOHW_HAVE_TREBLE 542 rb->sound_set(SOUND_TREBLE, (global || settings.tone_controls) 543 ? rb->global_settings->treble 544 : rb->sound_default(SOUND_TREBLE)); 545 #endif 546 547 #ifdef AUDIOHW_HAVE_EQ 548 for (int band = 0;; band++) 549 { 550 int setting = rb->sound_enum_hw_eq_band_setting(band, AUDIOHW_EQ_GAIN); 551 552 if (setting == -1) 553 break; 554 555 rb->sound_set(setting, (global || settings.tone_controls) 556 ? rb->global_settings->hw_eq_bands[band].gain 557 : rb->sound_default(setting)); 558 } 559 #endif /* AUDIOHW_HAVE_EQ */ 560 break; 561 562 case MPEG_AUDIO_CHANNEL_MODES: 563 rb->sound_set(SOUND_CHANNELS, (global || settings.channel_modes) 564 ? rb->global_settings->channel_config 565 : SOUND_CHAN_STEREO); 566 break; 567 568 case MPEG_AUDIO_CROSSFEED: 569 rb->dsp_set_crossfeed_type((global || settings.crossfeed) ? 570 rb->global_settings->crossfeed : 571 CROSSFEED_TYPE_NONE); 572 break; 573 574 case MPEG_AUDIO_EQUALIZER: 575 rb->dsp_eq_enable((global || settings.equalizer) ? 576 rb->global_settings->eq_enabled : false); 577 break; 578 579 case MPEG_AUDIO_DITHERING: 580 rb->dsp_dither_enable((global || settings.dithering) ? 581 rb->global_settings->dithering_enabled : false); 582 break; 583 } 584} 585 586/* Sync all audio settings to global or mpegplayer forced off */ 587static void sync_audio_settings(bool global) 588{ 589 static const int setting_index[] = 590 { 591 MPEG_AUDIO_TONE_CONTROLS, 592 MPEG_AUDIO_CHANNEL_MODES, 593 MPEG_AUDIO_CROSSFEED, 594 MPEG_AUDIO_EQUALIZER, 595 MPEG_AUDIO_DITHERING, 596 }; 597 unsigned i; 598 599 for (i = 0; i < ARRAYLEN(setting_index); i++) 600 { 601 sync_audio_setting(setting_index[i], global); 602 } 603} 604 605#ifndef HAVE_LCD_COLOR 606/* Cheapo splash implementation for the grey surface */ 607static void grey_splash(int ticks, const unsigned char *fmt, ...) 608{ 609 unsigned char buffer[256]; 610 int x, y, w, h; 611 int oldfg, oldmode; 612 613 va_list ap; 614 va_start(ap, fmt); 615 616 rb->vsnprintf(buffer, sizeof (buffer), fmt, ap); 617 618 va_end(ap); 619 620 grey_getstringsize(buffer, &w, &h); 621 622 oldfg = grey_get_foreground(); 623 oldmode = grey_get_drawmode(); 624 625 grey_set_drawmode(DRMODE_FG); 626 grey_set_foreground(GREY_LIGHTGRAY); 627 628 x = (LCD_WIDTH - w) / 2; 629 y = (LCD_HEIGHT - h) / 2; 630 631 grey_fillrect(x - 1, y - 1, w + 2, h + 2); 632 633 grey_set_foreground(GREY_BLACK); 634 635 grey_putsxy(x, y, buffer); 636 grey_drawrect(x - 2, y - 2, w + 4, h + 4); 637 638 grey_set_foreground(oldfg); 639 grey_set_drawmode(oldmode); 640 641 grey_update(); 642 643 if (ticks > 0) 644 rb->sleep(ticks); 645} 646#endif /* !HAVE_LCD_COLOR */ 647 648static void show_loading(struct vo_rect *rc) 649{ 650 int oldmode = mylcd_get_drawmode(); 651 mylcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); 652 mylcd_fillrect(rc->l-1, rc->t-1, rc->r - rc->l + 2, rc->b - rc->t + 2); 653 mylcd_set_drawmode(oldmode); 654 mylcd_splash(0, "Loading..."); 655} 656 657static void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc) 658{ 659 #define SLIDER_WIDTH (LCD_WIDTH-SLIDER_LMARGIN-SLIDER_RMARGIN) 660 #define SLIDER_X SLIDER_LMARGIN 661 #define SLIDER_Y (LCD_HEIGHT-SLIDER_HEIGHT-SLIDER_BMARGIN) 662 #define SLIDER_HEIGHT 8 663 #define SLIDER_TEXTMARGIN 1 664 #define SLIDER_LMARGIN 1 665 #define SLIDER_RMARGIN 1 666 #define SLIDER_TMARGIN 1 667 #define SLIDER_BMARGIN 1 668 #define SCREEN_MARGIN 1 669 670 struct hms hms; 671 char str[32]; 672 int text_w, text_h, text_y; 673 674 /* Put positition on left */ 675 ts_to_hms(pos, &hms); 676 hms_format(str, sizeof(str), &hms); 677 mylcd_getstringsize(str, NULL, &text_h); 678 text_y = SLIDER_Y - SLIDER_TEXTMARGIN - text_h; 679 680 if (rc == NULL) 681 { 682 int oldmode = mylcd_get_drawmode(); 683 mylcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID); 684 mylcd_fillrect(SLIDER_X, text_y, SLIDER_WIDTH, 685 LCD_HEIGHT - SLIDER_BMARGIN - text_y 686 - SLIDER_TMARGIN); 687 mylcd_set_drawmode(oldmode); 688 689 mylcd_putsxy(SLIDER_X, text_y, str); 690 691 /* Put duration on right */ 692 ts_to_hms(range, &hms); 693 hms_format(str, sizeof(str), &hms); 694 mylcd_getstringsize(str, &text_w, NULL); 695 696 mylcd_putsxy(SLIDER_X + SLIDER_WIDTH - text_w, text_y, str); 697 698 /* Draw slider */ 699 mylcd_drawrect(SLIDER_X, SLIDER_Y, SLIDER_WIDTH, SLIDER_HEIGHT); 700 mylcd_fillrect(SLIDER_X, SLIDER_Y, 701 muldiv_uint32(pos, SLIDER_WIDTH, range), 702 SLIDER_HEIGHT); 703 704 /* Update screen */ 705 mylcd_update_rect(SLIDER_X, text_y - SLIDER_TMARGIN, SLIDER_WIDTH, 706 LCD_HEIGHT - SLIDER_BMARGIN - text_y + SLIDER_TEXTMARGIN); 707 } 708 else 709 { 710 /* Just return slider rectangle */ 711 rc->l = SLIDER_X; 712 rc->t = text_y - SLIDER_TMARGIN; 713 rc->r = rc->l + SLIDER_WIDTH; 714 rc->b = rc->t + LCD_HEIGHT - SLIDER_BMARGIN - text_y; 715 } 716} 717 718static bool display_thumb_image(const struct vo_rect *rc) 719{ 720 bool retval = true; 721 unsigned ltgray = MYLCD_LIGHTGRAY; 722 unsigned dkgray = MYLCD_DARKGRAY; 723 724 int oldcolor = mylcd_get_foreground(); 725 726 if (!stream_display_thumb(rc)) 727 { 728 /* Display "No Frame" and erase any border */ 729 const char * const str = "No Frame"; 730 int x, y, w, h; 731 732 mylcd_getstringsize(str, &w, &h); 733 x = (rc->r + rc->l - w) / 2; 734 y = (rc->b + rc->t - h) / 2; 735 mylcd_putsxy(x, y, str); 736 737 mylcd_update_rect(x, y, w, h); 738 739 ltgray = dkgray = mylcd_get_background(); 740 retval = false; 741 } 742 743 /* Draw a raised border around the frame (or erase if no frame) */ 744 745 mylcd_set_foreground(ltgray); 746 747 mylcd_hline(rc->l-1, rc->r-1, rc->t-1); 748 mylcd_vline(rc->l-1, rc->t, rc->b-1); 749 750 mylcd_set_foreground(dkgray); 751 752 mylcd_hline(rc->l-1, rc->r, rc->b); 753 mylcd_vline(rc->r, rc->t-1, rc->b); 754 755 mylcd_set_foreground(oldcolor); 756 757 mylcd_update_rect(rc->l-1, rc->t-1, rc->r - rc->l + 2, 1); 758 mylcd_update_rect(rc->l-1, rc->t, 1, rc->b - rc->t); 759 mylcd_update_rect(rc->l-1, rc->b, rc->r - rc->l + 2, 1); 760 mylcd_update_rect(rc->r, rc->t, 1, rc->b - rc->t); 761 762 return retval; 763} 764 765/* Add an amount to the specified time - with saturation */ 766static uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range) 767{ 768 if (amount < 0) 769 { 770 uint32_t off = -amount; 771 if (range > off && val >= off) 772 val -= off; 773 else 774 val = 0; 775 } 776 else if (amount > 0) 777 { 778 uint32_t off = amount; 779 if (range > off && val <= range - off) 780 val += off; 781 else 782 val = range; 783 } 784 785 return val; 786} 787 788#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 789static void get_start_time_lcd_enable_hook(unsigned short id, void *param) 790{ 791 (void)id; 792 (void)param; 793 rb->button_queue_post(LCD_ENABLE_EVENT_0, 0); 794} 795#endif /* HAVE_LCD_ENABLE */ 796 797static int get_start_time(uint32_t duration) 798{ 799 int button = 0; 800 int tmo = TIMEOUT_NOBLOCK; 801 uint32_t resume_time = settings.resume_time; 802 struct vo_rect rc_vid, rc_bound; 803 uint32_t aspect_vid, aspect_bound; 804 bool sliding = false; 805 806 enum state_enum slider_state = STATE0; 807 808 mylcd_clear_display(); 809 mylcd_update(); 810 811#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 812 rb->add_event(LCD_EVENT_ACTIVATION, get_start_time_lcd_enable_hook); 813#endif 814 815 draw_slider(0, 100, &rc_bound); 816 rc_bound.b = rc_bound.t - SLIDER_TMARGIN; 817 rc_bound.t = SCREEN_MARGIN; 818 819 DEBUGF("rc_bound: %d, %d, %d, %d\n", rc_bound.l, rc_bound.t, 820 rc_bound.r, rc_bound.b); 821 822 rc_vid.l = rc_vid.t = 0; 823 if (!stream_vo_get_size((struct vo_ext *)&rc_vid.r)) 824 { 825 /* Can't get size - fill whole thing */ 826 rc_vid.r = rc_bound.r - rc_bound.l; 827 rc_vid.b = rc_bound.b - rc_bound.t; 828 } 829 830 /* Get aspect ratio of bounding rectangle and video in u16.16 */ 831 aspect_bound = ((rc_bound.r - rc_bound.l) << 16) / 832 (rc_bound.b - rc_bound.t); 833 834 DEBUGF("aspect_bound: %u.%02u\n", (unsigned)(aspect_bound >> 16), 835 (unsigned)(100*(aspect_bound & 0xffff) >> 16)); 836 837 aspect_vid = (rc_vid.r << 16) / rc_vid.b; 838 839 DEBUGF("aspect_vid: %u.%02u\n", (unsigned)(aspect_vid >> 16), 840 (unsigned)(100*(aspect_vid & 0xffff) >> 16)); 841 842 if (aspect_vid >= aspect_bound) 843 { 844 /* Video proportionally wider than or same as bounding rectangle */ 845 if (rc_vid.r > rc_bound.r - rc_bound.l) 846 { 847 rc_vid.r = rc_bound.r - rc_bound.l; 848 rc_vid.b = (rc_vid.r << 16) / aspect_vid; 849 } 850 /* else already fits */ 851 } 852 else 853 { 854 /* Video proportionally narrower than bounding rectangle */ 855 if (rc_vid.b > rc_bound.b - rc_bound.t) 856 { 857 rc_vid.b = rc_bound.b - rc_bound.t; 858 rc_vid.r = (aspect_vid * rc_vid.b) >> 16; 859 } 860 /* else already fits */ 861 } 862 863 /* Even width and height >= 2 */ 864 rc_vid.r = (rc_vid.r < 2) ? 2 : (rc_vid.r & ~1); 865 rc_vid.b = (rc_vid.b < 2) ? 2 : (rc_vid.b & ~1); 866 867 /* Center display in bounding rectangle */ 868 rc_vid.l = ((rc_bound.l + rc_bound.r) - rc_vid.r) / 2; 869 rc_vid.r += rc_vid.l; 870 871 rc_vid.t = ((rc_bound.t + rc_bound.b) - rc_vid.b) / 2; 872 rc_vid.b += rc_vid.t; 873 874 DEBUGF("rc_vid: %d, %d, %d, %d\n", rc_vid.l, rc_vid.t, 875 rc_vid.r, rc_vid.b); 876 877#ifndef HAVE_LCD_COLOR 878 stream_gray_show(true); 879#endif 880 881 while (slider_state < STATE9) 882 { 883 button = mpeg_button_get(tmo); 884 885 switch (button) 886 { 887 case BUTTON_NONE: 888 break; 889 890 /* Coarse (1 minute) control */ 891 case MPEG_START_TIME_DOWN: 892 case MPEG_START_TIME_DOWN | BUTTON_REPEAT: 893#ifdef MPEG_START_TIME_RC_DOWN 894 case MPEG_START_TIME_RC_DOWN: 895 case MPEG_START_TIME_RC_DOWN | BUTTON_REPEAT: 896#endif 897 resume_time = increment_time(resume_time, -60*TS_SECOND, duration); 898 slider_state = STATE0; 899 break; 900 901 case MPEG_START_TIME_UP: 902 case MPEG_START_TIME_UP | BUTTON_REPEAT: 903#ifdef MPEG_START_TIME_RC_UP 904 case MPEG_START_TIME_RC_UP: 905 case MPEG_START_TIME_RC_UP | BUTTON_REPEAT: 906#endif 907 resume_time = increment_time(resume_time, 60*TS_SECOND, duration); 908 slider_state = STATE0; 909 break; 910 911 /* Fine (1 second) control */ 912 case MPEG_START_TIME_LEFT: 913 case MPEG_START_TIME_LEFT | BUTTON_REPEAT: 914#ifdef MPEG_START_TIME_RC_LEFT 915 case MPEG_START_TIME_RC_LEFT: 916 case MPEG_START_TIME_RC_LEFT | BUTTON_REPEAT: 917#endif 918#ifdef MPEG_START_TIME_LEFT2 919 case MPEG_START_TIME_LEFT2: 920 case MPEG_START_TIME_LEFT2 | BUTTON_REPEAT: 921#endif 922 resume_time = increment_time(resume_time, -TS_SECOND, duration); 923 slider_state = STATE0; 924 break; 925 926 case MPEG_START_TIME_RIGHT: 927 case MPEG_START_TIME_RIGHT | BUTTON_REPEAT: 928#ifdef MPEG_START_TIME_RC_RIGHT 929 case MPEG_START_TIME_RC_RIGHT: 930 case MPEG_START_TIME_RC_RIGHT | BUTTON_REPEAT: 931#endif 932#ifdef MPEG_START_TIME_RIGHT2 933 case MPEG_START_TIME_RIGHT2: 934 case MPEG_START_TIME_RIGHT2 | BUTTON_REPEAT: 935#endif 936 resume_time = increment_time(resume_time, TS_SECOND, duration); 937 slider_state = STATE0; 938 break; 939 940 case MPEG_START_TIME_SELECT: 941#ifdef MPEG_START_TIME_RC_SELECT 942 case MPEG_START_TIME_RC_SELECT: 943#endif 944 settings.resume_time = resume_time; 945 button = MPEG_START_SEEK; 946 slider_state = STATE9; 947 break; 948 949 case MPEG_START_TIME_EXIT: 950#ifdef MPEG_START_TIME_RC_EXIT 951 case MPEG_START_TIME_RC_EXIT: 952#endif 953 button = MPEG_START_EXIT; 954 slider_state = STATE9; 955 break; 956 957 case ACTION_STD_CANCEL: 958 button = MPEG_START_QUIT; 959 slider_state = STATE9; 960 break; 961 962#ifdef HAVE_LCD_ENABLE 963 case LCD_ENABLE_EVENT_0: 964 if (slider_state == STATE2) 965 display_thumb_image(&rc_vid); 966 continue; 967#endif 968 969 default: 970 rb->default_event_handler(button); 971 rb->yield(); 972 continue; 973 } 974 975 switch (slider_state) 976 { 977 case STATE0: 978 if (!sliding) 979 { 980 if (rb->global_settings->talk_menu) 981 { 982 rb->talk_disable(true); 983#ifdef PLUGIN_USE_IRAM 984 mpegplayer_iram_restore(); 985#endif 986 } 987 trigger_cpu_boost(); 988 sliding = true; 989 } 990 stream_seek(resume_time, SEEK_SET); 991 show_loading(&rc_bound); 992 draw_slider(duration, resume_time, NULL); 993 slider_state = STATE1; 994 tmo = THUMB_DELAY; 995 break; 996 case STATE1: 997 display_thumb_image(&rc_vid); 998 slider_state = STATE2; 999 tmo = TIMEOUT_BLOCK; 1000 if (sliding) 1001 { 1002 cancel_cpu_boost(); 1003 if (rb->global_settings->talk_menu) 1004 { 1005#ifdef PLUGIN_USE_IRAM 1006 mpegplayer_iram_preserve(); 1007#endif 1008 rb->talk_disable(false); 1009 talk_val(resume_time / TS_SECOND, UNIT_TIME, false); 1010 talk_val(resume_time * 100 / duration, UNIT_PERCENT, true); 1011 } 1012 sliding = false; 1013 } 1014 default: 1015 break; 1016 } 1017 1018 rb->yield(); 1019 } 1020 1021#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 1022 rb->remove_event(LCD_EVENT_ACTIVATION, get_start_time_lcd_enable_hook); 1023#endif 1024#ifndef HAVE_LCD_COLOR 1025 stream_gray_show(false); 1026 grey_clear_display(); 1027 grey_update(); 1028#endif 1029 1030 cancel_cpu_boost(); 1031 1032 return button; 1033} 1034 1035static int show_start_menu(uint32_t duration) 1036{ 1037 int selected = 0; 1038 int result = 0; 1039 bool menu_quit = false; 1040 1041 MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, 1042 ID2P(LANG_RESTART_PLAYBACK), 1043 ID2P(LANG_RESUME_PLAYBACK), 1044 ID2P(LANG_SET_RESUME_TIME), 1045 ID2P(LANG_SETTINGS), 1046 ID2P(LANG_MENU_QUIT)); 1047 1048 if (rb->global_settings->talk_menu) 1049 { 1050#ifdef PLUGIN_USE_IRAM 1051 mpegplayer_iram_preserve(); 1052#endif 1053 rb->talk_disable(false); 1054 } 1055 1056 rb->button_clear_queue(); 1057 1058 while (!menu_quit) 1059 { 1060 mpeg_sysevent_clear(); 1061 result = rb->do_menu(&menu, &selected, NULL, false); 1062 1063 switch (result) 1064 { 1065 case MPEG_START_RESTART: 1066 settings.resume_time = 0; 1067 menu_quit = true; 1068 break; 1069 1070 case MPEG_START_RESUME: 1071 menu_quit = true; 1072 break; 1073 1074 case MPEG_START_SEEK: 1075 if (!stream_can_seek()) 1076 { 1077 rb->splash(HZ, ID2P(LANG_UNAVAILABLE)); 1078 break; 1079 } 1080 1081 result = get_start_time(duration); 1082 1083 if (result != MPEG_START_EXIT) 1084 menu_quit = true; 1085 break; 1086 1087 case MPEG_START_SETTINGS: 1088 mpeg_settings(); 1089 break; 1090 1091 default: 1092 result = MPEG_START_QUIT; 1093 menu_quit = true; 1094 break; 1095 } 1096 1097 if (mpeg_sysevent() != 0) 1098 { 1099 result = MPEG_START_QUIT; 1100 menu_quit = true; 1101 } 1102 } 1103 1104 if (rb->global_settings->talk_menu) 1105 { 1106 rb->talk_disable(true); 1107#ifdef PLUGIN_USE_IRAM 1108 mpegplayer_iram_restore(); 1109#endif 1110 } 1111 1112 return result; 1113} 1114 1115/* Return the desired resume action */ 1116int mpeg_start_menu(uint32_t duration) 1117{ 1118 mpeg_sysevent_clear(); 1119 1120 switch (settings.resume_options) 1121 { 1122 case MPEG_RESUME_MENU_IF_INCOMPLETE: 1123 if (!stream_can_seek() || settings.resume_time == 0) 1124 { 1125 case MPEG_RESUME_RESTART: 1126 settings.resume_time = 0; 1127 return MPEG_START_RESTART; 1128 } 1129 default: 1130 case MPEG_RESUME_MENU_ALWAYS: 1131 return show_start_menu(duration); 1132 case MPEG_RESUME_ALWAYS: 1133 return MPEG_START_SEEK; 1134 } 1135} 1136 1137int mpeg_menu(void) 1138{ 1139 int result; 1140 1141 MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_sysevent_callback, 1142 ID2P(LANG_SETTINGS), 1143 ID2P(LANG_RESUME_PLAYBACK), 1144 ID2P(LANG_MENU_QUIT)); 1145 1146 if (rb->global_settings->talk_menu) 1147 { 1148#ifdef PLUGIN_USE_IRAM 1149 mpegplayer_iram_preserve(); 1150#endif 1151 rb->talk_disable(false); 1152 } 1153 1154 rb->button_clear_queue(); 1155 1156 mpeg_sysevent_clear(); 1157 1158 result = rb->do_menu(&menu, NULL, NULL, false); 1159 1160 switch (result) 1161 { 1162 case MPEG_MENU_SETTINGS: 1163 mpeg_settings(); 1164 break; 1165 1166 case MPEG_MENU_RESUME: 1167 break; 1168 1169 case MPEG_MENU_QUIT: 1170 break; 1171 1172 default: 1173 break; 1174 } 1175 1176 if (mpeg_sysevent() != 0) 1177 result = MPEG_MENU_QUIT; 1178 1179 if (rb->global_settings->talk_menu) 1180 { 1181 rb->talk_disable(true); 1182#ifdef PLUGIN_USE_IRAM 1183 mpegplayer_iram_restore(); 1184#endif 1185 } 1186 1187 return result; 1188} 1189 1190static void display_options(void) 1191{ 1192 int selected = 0; 1193 int result; 1194 bool menu_quit = false; 1195 1196 MENUITEM_STRINGLIST(menu, "Display Options", mpeg_sysevent_callback, 1197#if MPEG_OPTION_DITHERING_ENABLED 1198 ID2P(LANG_DITHERING), 1199#endif 1200 ID2P(LANG_DISPLAY_FPS), 1201 ID2P(LANG_LIMIT_FPS), 1202 ID2P(LANG_SKIP_FRAMES), 1203#ifdef HAVE_BACKLIGHT_BRIGHTNESS 1204 ID2P(LANG_BACKLIGHT_BRIGHTNESS), 1205#endif 1206 ); 1207 1208 rb->button_clear_queue(); 1209 1210 while (!menu_quit) 1211 { 1212 mpeg_sysevent_clear(); 1213 result = rb->do_menu(&menu, &selected, NULL, false); 1214 1215 switch (result) 1216 { 1217#if MPEG_OPTION_DITHERING_ENABLED 1218 case MPEG_OPTION_DITHERING: 1219 result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0; 1220 mpeg_set_option(rb->str(LANG_DITHERING), &result, RB_INT, noyes, 2, NULL); 1221 settings.displayoptions = 1222 (settings.displayoptions & ~LCD_YUV_DITHER) 1223 | ((result != 0) ? LCD_YUV_DITHER : 0); 1224 rb->lcd_yuv_set_options(settings.displayoptions); 1225 break; 1226#endif /* MPEG_OPTION_DITHERING_ENABLED */ 1227 1228 case MPEG_OPTION_DISPLAY_FPS: 1229 mpeg_set_option(rb->str(LANG_DISPLAY_FPS), &settings.showfps, RB_INT, 1230 noyes, 2, NULL); 1231 break; 1232 1233 case MPEG_OPTION_LIMIT_FPS: 1234 mpeg_set_option(rb->str(LANG_LIMIT_FPS), &settings.limitfps, RB_INT, 1235 noyes, 2, NULL); 1236 break; 1237 1238 case MPEG_OPTION_SKIP_FRAMES: 1239 mpeg_set_option(rb->str(LANG_SKIP_FRAMES), &settings.skipframes, RB_INT, 1240 noyes, 2, NULL); 1241 break; 1242 1243#ifdef HAVE_BACKLIGHT_BRIGHTNESS 1244 case MPEG_OPTION_BACKLIGHT_BRIGHTNESS: 1245 result = settings.backlight_brightness; 1246 mpeg_backlight_update_brightness(result); 1247 mpeg_set_int(rb->str(LANG_BACKLIGHT_BRIGHTNESS), NULL, UNIT_INT, &result, 1248 backlight_brightness_function, 1, -1, 1249 MAX_BRIGHTNESS_SETTING - MIN_BRIGHTNESS_SETTING, 1250 backlight_brightness_formatter, 1251 backlight_brightness_getlang); 1252 settings.backlight_brightness = result; 1253 mpeg_backlight_update_brightness(-1); 1254 break; 1255#endif /* HAVE_BACKLIGHT_BRIGHTNESS */ 1256 1257 default: 1258 menu_quit = true; 1259 break; 1260 } 1261 1262 if (mpeg_sysevent() != 0) 1263 menu_quit = true; 1264 } 1265} 1266 1267static void audio_options(void) 1268{ 1269 int selected = 0; 1270 int result; 1271 bool menu_quit = false; 1272 1273 MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_sysevent_callback, 1274 ID2P(LANG_TONE_CONTROLS), 1275 ID2P(LANG_CHANNEL_CONFIGURATION), 1276 ID2P(LANG_CROSSFEED), 1277 ID2P(LANG_EQUALIZER), 1278 ID2P(LANG_DITHERING)); 1279 1280 rb->button_clear_queue(); 1281 1282 while (!menu_quit) 1283 { 1284 mpeg_sysevent_clear(); 1285 result = rb->do_menu(&menu, &selected, NULL, false); 1286 1287 switch (result) 1288 { 1289 case MPEG_AUDIO_TONE_CONTROLS: 1290 mpeg_set_option(rb->str(LANG_TONE_CONTROLS), &settings.tone_controls, RB_INT, 1291 globaloff, 2, NULL); 1292 sync_audio_setting(result, false); 1293 break; 1294 1295 case MPEG_AUDIO_CHANNEL_MODES: 1296 mpeg_set_option(rb->str(LANG_CHANNEL_CONFIGURATION), &settings.channel_modes, 1297 RB_INT, globaloff, 2, NULL); 1298 sync_audio_setting(result, false); 1299 break; 1300 1301 case MPEG_AUDIO_CROSSFEED: 1302 mpeg_set_option(rb->str(LANG_CROSSFEED), &settings.crossfeed, RB_INT, 1303 globaloff, 2, NULL); 1304 sync_audio_setting(result, false); 1305 break; 1306 1307 case MPEG_AUDIO_EQUALIZER: 1308 mpeg_set_option(rb->str(LANG_EQUALIZER), &settings.equalizer, RB_INT, 1309 globaloff, 2, NULL); 1310 sync_audio_setting(result, false); 1311 break; 1312 1313 case MPEG_AUDIO_DITHERING: 1314 mpeg_set_option(rb->str(LANG_DITHERING), &settings.dithering, RB_INT, 1315 globaloff, 2, NULL); 1316 sync_audio_setting(result, false); 1317 break; 1318 1319 default: 1320 menu_quit = true; 1321 break; 1322 } 1323 1324 if (mpeg_sysevent() != 0) 1325 menu_quit = true; 1326 } 1327} 1328 1329static void resume_options(void) 1330{ 1331 static const struct opt_items items[MPEG_RESUME_NUM_OPTIONS] = { 1332 [MPEG_RESUME_MENU_ALWAYS] = 1333 { STR(LANG_FORCE_START_MENU) }, 1334 [MPEG_RESUME_MENU_IF_INCOMPLETE] = 1335 { STR(LANG_CONDITIONAL_START_MENU) }, 1336 [MPEG_RESUME_ALWAYS] = 1337 { STR(LANG_AUTO_RESUME) }, 1338 [MPEG_RESUME_RESTART] = 1339 { STR(LANG_RESTART_PLAYBACK) }, 1340 }; 1341 1342 mpeg_set_option(rb->str(LANG_MENU_RESUME_OPTIONS), &settings.resume_options, 1343 RB_INT, items, MPEG_RESUME_NUM_OPTIONS, NULL); 1344} 1345 1346static void clear_resume_count(void) 1347{ 1348 settings.resume_count = 0; 1349 configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config), 1350 SETTINGS_VERSION); 1351} 1352 1353static void mpeg_settings(void) 1354{ 1355 int selected = 0; 1356 int result; 1357 bool menu_quit = false; 1358 1359 MENUITEM_STRINGLIST(menu, "Settings", mpeg_sysevent_callback, 1360 ID2P(LANG_MENU_DISPLAY_OPTIONS), 1361 ID2P(LANG_MENU_AUDIO_OPTIONS), 1362 ID2P(LANG_MENU_RESUME_OPTIONS), 1363 ID2P(LANG_MENU_PLAY_MODE), 1364 ID2P(LANG_CLEAR_ALL_RESUMES)); 1365 1366 rb->button_clear_queue(); 1367 1368 while (!menu_quit) 1369 { 1370 mpeg_sysevent_clear(); 1371 1372 result = rb->do_menu(&menu, &selected, NULL, false); 1373 1374 switch (result) 1375 { 1376 case MPEG_SETTING_DISPLAY_SETTINGS: 1377 display_options(); 1378 break; 1379 1380 case MPEG_SETTING_AUDIO_SETTINGS: 1381 audio_options(); 1382 break; 1383 1384 case MPEG_SETTING_ENABLE_START_MENU: 1385 resume_options(); 1386 break; 1387 1388 case MPEG_SETTING_PLAY_MODE: 1389 mpeg_set_option(rb->str(LANG_MENU_PLAY_MODE), &settings.play_mode, 1390 RB_INT, singleall, 2, NULL); 1391 break; 1392 1393 case MPEG_SETTING_CLEAR_RESUMES: 1394 clear_resume_count(); 1395 break; 1396 1397 default: 1398 menu_quit = true; 1399 break; 1400 } 1401 1402 if (mpeg_sysevent() != 0) 1403 menu_quit = true; 1404 } 1405} 1406 1407void init_settings(const char* filename) 1408{ 1409 /* Set the default settings */ 1410 settings.showfps = 0; /* Do not show FPS */ 1411 settings.limitfps = 1; /* Limit FPS */ 1412 settings.skipframes = 1; /* Skip frames */ 1413 settings.play_mode = 0; /* Play single video */ 1414 settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */ 1415 settings.resume_count = 0; 1416#ifdef HAVE_BACKLIGHT_BRIGHTNESS 1417 settings.backlight_brightness = -1; /* Use default setting */ 1418#endif 1419#if MPEG_OPTION_DITHERING_ENABLED 1420 settings.displayoptions = 0; /* No visual effects */ 1421#endif 1422 settings.tone_controls = false; 1423 settings.channel_modes = false; 1424 settings.crossfeed = false; 1425 settings.equalizer = false; 1426 settings.dithering = false; 1427 1428 if (configfile_load(SETTINGS_FILENAME, config, ARRAYLEN(config), 1429 SETTINGS_MIN_VERSION) < 0) 1430 { 1431 /* Generate a new config file with default values */ 1432 configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config), 1433 SETTINGS_VERSION); 1434 } 1435 1436 rb->strlcpy(settings.resume_filename, filename, MAX_PATH); 1437 1438 /* get the resume time for the current mpeg if it exists */ 1439 if ((settings.resume_time = configfile_get_value 1440 (SETTINGS_FILENAME, filename)) < 0) 1441 { 1442 settings.resume_time = 0; 1443 } 1444 1445#if MPEG_OPTION_DITHERING_ENABLED 1446 rb->lcd_yuv_set_options(settings.displayoptions); 1447#endif 1448 1449 /* Set our audio options */ 1450 sync_audio_settings(false); 1451} 1452 1453void save_settings(void) 1454{ 1455 unsigned i; 1456 for (i = 0; i < ARRAYLEN(config); i++) 1457 { 1458 configfile_update_entry(SETTINGS_FILENAME, config[i].name, 1459 *(config[i].int_p)); 1460 } 1461 1462 /* If this was a new resume entry then update the total resume count */ 1463 if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename, 1464 settings.resume_time) == 0) 1465 { 1466 configfile_update_entry(SETTINGS_FILENAME, "Resume count", 1467 ++settings.resume_count); 1468 } 1469 1470 /* Restore audio options */ 1471 sync_audio_settings(true); 1472}