fix red.
[kugel-rb.git] / apps / plugins / mpegplayer / mpeg_settings.c
blob7ca000553f5ea41682c1448f467a75f927359297
1 #include "plugin.h"
2 #include "lib/helper.h"
3 #include "lib/configfile.h"
5 #include "mpegplayer.h"
6 #include "mpeg_settings.h"
8 struct mpeg_settings settings;
10 #define THUMB_DELAY (75*HZ/100)
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_RIGHT BUTTON_RIGHT
17 #define MPEG_START_TIME_LEFT BUTTON_LEFT
18 #define MPEG_START_TIME_UP BUTTON_UP
19 #define MPEG_START_TIME_DOWN BUTTON_DOWN
20 #define MPEG_START_TIME_EXIT BUTTON_OFF
22 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
23 #define MPEG_START_TIME_SELECT BUTTON_PLAY
24 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
25 #define MPEG_START_TIME_LEFT BUTTON_LEFT
26 #define MPEG_START_TIME_UP BUTTON_UP
27 #define MPEG_START_TIME_DOWN BUTTON_DOWN
28 #define MPEG_START_TIME_EXIT BUTTON_POWER
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_RIGHT BUTTON_RIGHT
35 #define MPEG_START_TIME_LEFT BUTTON_LEFT
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
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_SCROLL_DOWN BUTTON_VOL_DOWN
47 #define MPEG_START_TIME_SCROLL_UP BUTTON_VOL_UP
48 #define MPEG_START_TIME_EXIT BUTTON_POWER
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)
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_SCROLL_DOWN BUTTON_VOL_DOWN
64 #define MPEG_START_TIME_SCROLL_UP BUTTON_VOL_UP
65 #define MPEG_START_TIME_EXIT BUTTON_POWER
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)
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
82 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
83 #define MPEG_START_TIME_SELECT BUTTON_SELECT
84 #define MPEG_START_TIME_SCROLL_UP BUTTON_SCROLL_BACK
85 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_SCROLL_FWD
86 #define MPEG_START_TIME_LEFT BUTTON_LEFT
87 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
88 #define MPEG_START_TIME_UP BUTTON_UP
89 #define MPEG_START_TIME_DOWN BUTTON_DOWN
90 #define MPEG_START_TIME_EXIT BUTTON_POWER
92 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
93 #define MPEG_START_TIME_SELECT BUTTON_SELECT
94 #define MPEG_START_TIME_SCROLL_UP BUTTON_SCROLL_BACK
95 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_SCROLL_FWD
96 #define MPEG_START_TIME_LEFT BUTTON_LEFT
97 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
98 #define MPEG_START_TIME_UP BUTTON_UP
99 #define MPEG_START_TIME_DOWN BUTTON_DOWN
100 #define MPEG_START_TIME_EXIT (BUTTON_HOME|BUTTON_REPEAT)
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_SCROLL_UP BUTTON_VOL_UP
107 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_VOL_DOWN
108 #define MPEG_START_TIME_LEFT BUTTON_LEFT
109 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
110 #define MPEG_START_TIME_UP BUTTON_UP
111 #define MPEG_START_TIME_DOWN BUTTON_DOWN
112 #define MPEG_START_TIME_EXIT BUTTON_POWER
114 #elif CONFIG_KEYPAD == MROBE500_PAD
115 #define MPEG_START_TIME_SELECT BUTTON_RC_HEART
116 #define MPEG_START_TIME_SCROLL_UP BUTTON_RC_VOL_UP
117 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_RC_VOL_DOWN
118 #define MPEG_START_TIME_LEFT BUTTON_LEFT
119 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
120 #define MPEG_START_TIME_UP BUTTON_RC_PLAY
121 #define MPEG_START_TIME_DOWN BUTTON_RC_DOWN
122 #define MPEG_START_TIME_EXIT BUTTON_POWER
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_SCROLL_DOWN BUTTON_MENU
131 #define MPEG_START_TIME_SCROLL_UP BUTTON_PLAY
132 #define MPEG_START_TIME_EXIT BUTTON_POWER
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
142 #elif CONFIG_KEYPAD == COWOND2_PAD
143 #define MPEG_START_TIME_EXIT BUTTON_POWER
145 #elif CONFIG_KEYPAD == IAUDIO67_PAD
146 #define MPEG_START_TIME_SELECT BUTTON_MENU
147 #define MPEG_START_TIME_LEFT BUTTON_LEFT
148 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
149 #define MPEG_START_TIME_UP BUTTON_STOP
150 #define MPEG_START_TIME_DOWN BUTTON_PLAY
151 #define MPEG_START_TIME_EXIT BUTTON_POWER
153 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
154 #define MPEG_START_TIME_SELECT BUTTON_SELECT
155 #define MPEG_START_TIME_SCROLL_UP BUTTON_PLAY
156 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_MENU
157 #define MPEG_START_TIME_LEFT BUTTON_LEFT
158 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
159 #define MPEG_START_TIME_UP BUTTON_UP
160 #define MPEG_START_TIME_DOWN BUTTON_DOWN
161 #define MPEG_START_TIME_EXIT BUTTON_BACK
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_SCROLL_DOWN BUTTON_VOL_DOWN
170 #define MPEG_START_TIME_SCROLL_UP BUTTON_VOL_UP
171 #define MPEG_START_TIME_EXIT BUTTON_POWER
173 #elif CONFIG_KEYPAD == ONDAVX747_PAD
174 #define MPEG_START_TIME_EXIT BUTTON_POWER
176 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
177 #define MPEG_START_TIME_SELECT BUTTON_PLAY
178 #define MPEG_START_TIME_LEFT BUTTON_LEFT
179 #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
180 #define MPEG_START_TIME_UP BUTTON_UP
181 #define MPEG_START_TIME_DOWN BUTTON_DOWN
182 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_FFWD
183 #define MPEG_START_TIME_SCROLL_UP BUTTON_REW
184 #define MPEG_START_TIME_EXIT BUTTON_REC
186 #else
187 #error No keymap defined!
188 #endif
190 #ifdef HAVE_TOUCHSCREEN
191 #ifndef MPEG_START_TIME_SELECT
192 #define MPEG_START_TIME_SELECT BUTTON_CENTER
193 #endif
194 #ifndef MPEG_START_TIME_SCROLL_UP
195 #define MPEG_START_TIME_SCROLL_UP BUTTON_TOPRIGHT
196 #endif
197 #ifndef MPEG_START_TIME_SCROLL_DOWN
198 #define MPEG_START_TIME_SCROLL_DOWN BUTTON_TOPLEFT
199 #endif
200 #ifndef MPEG_START_TIME_LEFT
201 #define MPEG_START_TIME_LEFT BUTTON_MIDLEFT
202 #endif
203 #ifndef MPEG_START_TIME_RIGHT
204 #define MPEG_START_TIME_RIGHT BUTTON_MIDRIGHT
205 #endif
206 #ifndef MPEG_START_TIME_UP
207 #define MPEG_START_TIME_UP BUTTON_TOPMIDDLE
208 #endif
209 #ifndef MPEG_START_TIME_DOWN
210 #define MPEG_START_TIME_DOWN BUTTON_BOTTOMMIDDLE
211 #endif
212 #ifndef MPEG_START_TIME_EXIT
213 #define MPEG_START_TIME_EXIT BUTTON_TOPLEFT
214 #endif
215 #endif
217 static struct configdata config[] =
219 {TYPE_INT, 0, 2, { .int_p = &settings.showfps }, "Show FPS", NULL},
220 {TYPE_INT, 0, 2, { .int_p = &settings.limitfps }, "Limit FPS", NULL},
221 {TYPE_INT, 0, 2, { .int_p = &settings.skipframes }, "Skip frames", NULL},
222 {TYPE_INT, 0, INT_MAX, { .int_p = &settings.resume_count }, "Resume count",
223 NULL},
224 {TYPE_INT, 0, MPEG_RESUME_NUM_OPTIONS,
225 { .int_p = &settings.resume_options }, "Resume options", NULL},
226 #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) || defined(SANSA_FUZE) || defined(SANSA_E200V2)
227 {TYPE_INT, 0, INT_MAX, { .int_p = &settings.displayoptions },
228 "Display options", NULL},
229 #endif
230 {TYPE_INT, 0, 2, { .int_p = &settings.tone_controls }, "Tone controls",
231 NULL},
232 {TYPE_INT, 0, 2, { .int_p = &settings.channel_modes }, "Channel modes",
233 NULL},
234 {TYPE_INT, 0, 2, { .int_p = &settings.crossfeed }, "Crossfeed", NULL},
235 {TYPE_INT, 0, 2, { .int_p = &settings.equalizer }, "Equalizer", NULL},
236 {TYPE_INT, 0, 2, { .int_p = &settings.dithering }, "Dithering", NULL},
237 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
238 {TYPE_INT, -1, INT_MAX, { .int_p = &settings.backlight_brightness },
239 "Backlight brightness", NULL},
240 #endif
243 static const struct opt_items noyes[2] = {
244 { "No", -1 },
245 { "Yes", -1 },
248 static const struct opt_items enabledisable[2] = {
249 { "Disable", -1 },
250 { "Enable", -1 },
253 static const struct opt_items globaloff[2] = {
254 { "Force off", -1 },
255 { "Use sound setting", -1 },
258 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
259 #define BACKLIGHT_OPTION_DEFAULT "Use setting"
260 #endif
262 static void mpeg_settings(void);
263 static long mpeg_menu_sysevent_id;
265 void mpeg_menu_sysevent_clear(void)
267 mpeg_menu_sysevent_id = 0;
270 int mpeg_menu_sysevent_callback(int btn, const struct menu_item_ex *menu)
272 switch (btn)
274 case SYS_USB_CONNECTED:
275 case SYS_POWEROFF:
276 mpeg_menu_sysevent_id = btn;
277 return ACTION_STD_CANCEL;
280 return btn;
281 (void)menu;
284 long mpeg_menu_sysevent(void)
286 return mpeg_menu_sysevent_id;
289 void mpeg_menu_sysevent_handle(void)
291 long id = mpeg_menu_sysevent();
292 if (id != 0)
293 rb->default_event_handler(id);
296 static bool mpeg_set_option(const char* string,
297 void* variable,
298 enum optiontype type,
299 const struct opt_items* options,
300 int numoptions,
301 void (*function)(int))
303 mpeg_menu_sysevent_clear();
305 /* This eats SYS_POWEROFF - :\ */
306 bool usb = rb->set_option(string, variable, type, options, numoptions,
307 function);
309 if (usb)
310 mpeg_menu_sysevent_id = ACTION_STD_CANCEL;
312 return usb;
315 #ifdef HAVE_BACKLIGHT_BRIGHTNESS /* Only used for this atm */
316 static bool mpeg_set_int(const char *string, const char *unit,
317 int voice_unit, const int *variable,
318 void (*function)(int), int step,
319 int min,
320 int max,
321 const char* (*formatter)(char*, size_t, int, const char*))
323 mpeg_menu_sysevent_clear();
325 bool usb = rb->set_int(string, unit, voice_unit, variable, function,
326 step, min, max, formatter);
328 if (usb)
329 mpeg_menu_sysevent_id = ACTION_STD_CANCEL;
331 return usb;
333 #endif /* HAVE_BACKLIGHT_BRIGHTNESS */
335 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
336 void mpeg_backlight_update_brightness(int value)
338 if (value >= 0)
340 value += MIN_BRIGHTNESS_SETTING;
341 backlight_brightness_set(value);
343 else
345 backlight_brightness_use_setting();
349 static void backlight_brightness_function(int value)
351 mpeg_backlight_update_brightness(value);
354 static const char* backlight_brightness_formatter(char *buf, size_t length,
355 int value, const char *input)
357 (void)input;
359 if (value < 0)
360 return BACKLIGHT_OPTION_DEFAULT;
361 else
362 rb->snprintf(buf, length, "%d", value + MIN_BRIGHTNESS_SETTING);
363 return buf;
365 #endif /* HAVE_BACKLIGHT_BRIGHTNESS */
367 /* Sync a particular audio setting to global or mpegplayer forced off */
368 static void sync_audio_setting(int setting, bool global)
370 int val0, val1;
372 switch (setting)
374 case MPEG_AUDIO_TONE_CONTROLS:
375 if (global || settings.tone_controls)
377 val0 = rb->global_settings->bass;
378 val1 = rb->global_settings->treble;
380 else
382 val0 = rb->sound_default(SOUND_BASS);
383 val1 = rb->sound_default(SOUND_TREBLE);
385 rb->sound_set(SOUND_BASS, val0);
386 rb->sound_set(SOUND_TREBLE, val1);
387 break;
389 case MPEG_AUDIO_CHANNEL_MODES:
390 val0 = (global || settings.channel_modes) ?
391 rb->global_settings->channel_config :
392 SOUND_CHAN_STEREO;
393 rb->sound_set(SOUND_CHANNELS, val0);
394 break;
396 case MPEG_AUDIO_CROSSFEED:
397 rb->dsp_set_crossfeed((global || settings.crossfeed) ?
398 rb->global_settings->crossfeed : false);
399 break;
401 case MPEG_AUDIO_EQUALIZER:
402 rb->dsp_set_eq((global || settings.equalizer) ?
403 rb->global_settings->eq_enabled : false);
404 break;
406 case MPEG_AUDIO_DITHERING:
407 rb->dsp_dither_enable((global || settings.dithering) ?
408 rb->global_settings->dithering_enabled : false);
409 break;
413 /* Sync all audio settings to global or mpegplayer forced off */
414 static void sync_audio_settings(bool global)
416 static const int setting_index[] =
418 MPEG_AUDIO_TONE_CONTROLS,
419 MPEG_AUDIO_CHANNEL_MODES,
420 MPEG_AUDIO_CROSSFEED,
421 MPEG_AUDIO_EQUALIZER,
422 MPEG_AUDIO_DITHERING,
424 unsigned i;
426 for (i = 0; i < ARRAYLEN(setting_index); i++)
428 sync_audio_setting(setting_index[i], global);
432 #ifndef HAVE_LCD_COLOR
433 /* Cheapo splash implementation for the grey surface */
434 static void grey_splash(int ticks, const unsigned char *fmt, ...)
436 unsigned char buffer[256];
437 int x, y, w, h;
438 int oldfg, oldmode;
440 va_list ap;
441 va_start(ap, fmt);
443 rb->vsnprintf(buffer, sizeof (buffer), fmt, ap);
445 va_end(ap);
447 grey_getstringsize(buffer, &w, &h);
449 oldfg = grey_get_foreground();
450 oldmode = grey_get_drawmode();
452 grey_set_drawmode(DRMODE_FG);
453 grey_set_foreground(GREY_LIGHTGRAY);
455 x = (LCD_WIDTH - w) / 2;
456 y = (LCD_HEIGHT - h) / 2;
458 grey_fillrect(x - 1, y - 1, w + 2, h + 2);
460 grey_set_foreground(GREY_BLACK);
462 grey_putsxy(x, y, buffer);
463 grey_drawrect(x - 2, y - 2, w + 4, h + 4);
465 grey_set_foreground(oldfg);
466 grey_set_drawmode(oldmode);
468 grey_update();
470 if (ticks > 0)
471 rb->sleep(ticks);
473 #endif /* !HAVE_LCD_COLOR */
475 static void show_loading(struct vo_rect *rc)
477 int oldmode = lcd_(get_drawmode)();
478 lcd_(set_drawmode)(DRMODE_SOLID | DRMODE_INVERSEVID);
479 lcd_(fillrect)(rc->l-1, rc->t-1, rc->r - rc->l + 2, rc->b - rc->t + 2);
480 lcd_(set_drawmode)(oldmode);
481 lcd_(splash)(0, "Loading...");
484 static void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc)
486 #define SLIDER_WIDTH (LCD_WIDTH-SLIDER_LMARGIN-SLIDER_RMARGIN)
487 #define SLIDER_X SLIDER_LMARGIN
488 #define SLIDER_Y (LCD_HEIGHT-SLIDER_HEIGHT-SLIDER_BMARGIN)
489 #define SLIDER_HEIGHT 8
490 #define SLIDER_TEXTMARGIN 1
491 #define SLIDER_LMARGIN 1
492 #define SLIDER_RMARGIN 1
493 #define SLIDER_TMARGIN 1
494 #define SLIDER_BMARGIN 1
495 #define SCREEN_MARGIN 1
497 struct hms hms;
498 char str[32];
499 int text_w, text_h, text_y;
501 /* Put positition on left */
502 ts_to_hms(pos, &hms);
503 hms_format(str, sizeof(str), &hms);
504 lcd_(getstringsize)(str, NULL, &text_h);
505 text_y = SLIDER_Y - SLIDER_TEXTMARGIN - text_h;
507 if (rc == NULL)
509 int oldmode = lcd_(get_drawmode)();
510 lcd_(set_drawmode)(DRMODE_BG | DRMODE_INVERSEVID);
511 lcd_(fillrect)(SLIDER_X, text_y, SLIDER_WIDTH,
512 LCD_HEIGHT - SLIDER_BMARGIN - text_y
513 - SLIDER_TMARGIN);
514 lcd_(set_drawmode)(oldmode);
516 lcd_(putsxy)(SLIDER_X, text_y, str);
518 /* Put duration on right */
519 ts_to_hms(range, &hms);
520 hms_format(str, sizeof(str), &hms);
521 lcd_(getstringsize)(str, &text_w, NULL);
523 lcd_(putsxy)(SLIDER_X + SLIDER_WIDTH - text_w, text_y, str);
525 /* Draw slider */
526 lcd_(drawrect)(SLIDER_X, SLIDER_Y, SLIDER_WIDTH, SLIDER_HEIGHT);
527 lcd_(fillrect)(SLIDER_X, SLIDER_Y,
528 muldiv_uint32(pos, SLIDER_WIDTH, range),
529 SLIDER_HEIGHT);
531 /* Update screen */
532 lcd_(update_rect)(SLIDER_X, text_y - SLIDER_TMARGIN, SLIDER_WIDTH,
533 LCD_HEIGHT - SLIDER_BMARGIN - text_y + SLIDER_TEXTMARGIN);
535 else
537 /* Just return slider rectangle */
538 rc->l = SLIDER_X;
539 rc->t = text_y - SLIDER_TMARGIN;
540 rc->r = rc->l + SLIDER_WIDTH;
541 rc->b = rc->t + LCD_HEIGHT - SLIDER_BMARGIN - text_y;
545 static bool display_thumb_image(const struct vo_rect *rc)
547 if (!stream_display_thumb(rc))
549 lcd_(splash)(0, "Frame not available");
550 return false;
553 /* Draw a raised border around the frame */
554 int oldcolor = lcd_(get_foreground)();
555 lcd_(set_foreground)(DRAW_LIGHTGRAY);
557 lcd_(hline)(rc->l-1, rc->r-1, rc->t-1);
558 lcd_(vline)(rc->l-1, rc->t, rc->b-1);
560 lcd_(set_foreground)(DRAW_DARKGRAY);
562 lcd_(hline)(rc->l-1, rc->r, rc->b);
563 lcd_(vline)(rc->r, rc->t-1, rc->b);
565 lcd_(set_foreground)(oldcolor);
567 lcd_(update_rect)(rc->l-1, rc->t-1, rc->r - rc->l + 2, 1);
568 lcd_(update_rect)(rc->l-1, rc->t, 1, rc->b - rc->t);
569 lcd_(update_rect)(rc->l-1, rc->b, rc->r - rc->l + 2, 1);
570 lcd_(update_rect)(rc->r, rc->t, 1, rc->b - rc->t);
572 return true;
575 /* Add an amount to the specified time - with saturation */
576 static uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range)
578 if (amount < 0)
580 uint32_t off = -amount;
581 if (range > off && val >= off)
582 val -= off;
583 else
584 val = 0;
586 else if (amount > 0)
588 uint32_t off = amount;
589 if (range > off && val <= range - off)
590 val += off;
591 else
592 val = range;
595 return val;
598 #if defined(HAVE_LCD_ENABLE) && defined(HAVE_LCD_COLOR)
599 static void get_start_time_lcd_enable_hook(void)
601 rb->queue_post(rb->button_queue, LCD_ENABLE_EVENT_0, 0);
603 #endif /* HAVE_LCD_ENABLE */
605 static int get_start_time(uint32_t duration)
607 int button = 0;
608 int tmo = TIMEOUT_NOBLOCK;
609 uint32_t resume_time = settings.resume_time;
610 struct vo_rect rc_vid, rc_bound;
611 uint32_t aspect_vid, aspect_bound;
613 enum state_enum slider_state = state0;
615 lcd_(clear_display)();
616 lcd_(update)();
618 #if defined(HAVE_LCD_ENABLE) && defined(HAVE_LCD_COLOR)
619 rb->lcd_activation_set_hook(get_start_time_lcd_enable_hook);
620 #endif
622 draw_slider(0, 100, &rc_bound);
623 rc_bound.b = rc_bound.t - SLIDER_TMARGIN;
624 rc_bound.t = SCREEN_MARGIN;
626 DEBUGF("rc_bound: %d, %d, %d, %d\n", rc_bound.l, rc_bound.t,
627 rc_bound.r, rc_bound.b);
629 rc_vid.l = rc_vid.t = 0;
630 if (!stream_vo_get_size((struct vo_ext *)&rc_vid.r))
632 /* Can't get size - fill whole thing */
633 rc_vid.r = rc_bound.r - rc_bound.l;
634 rc_vid.b = rc_bound.b - rc_bound.t;
637 /* Get aspect ratio of bounding rectangle and video in u16.16 */
638 aspect_bound = ((rc_bound.r - rc_bound.l) << 16) /
639 (rc_bound.b - rc_bound.t);
641 DEBUGF("aspect_bound: %u.%02u\n", (unsigned)(aspect_bound >> 16),
642 (unsigned)(100*(aspect_bound & 0xffff) >> 16));
644 aspect_vid = (rc_vid.r << 16) / rc_vid.b;
646 DEBUGF("aspect_vid: %u.%02u\n", (unsigned)(aspect_vid >> 16),
647 (unsigned)(100*(aspect_vid & 0xffff) >> 16));
649 if (aspect_vid >= aspect_bound)
651 /* Video proportionally wider than or same as bounding rectangle */
652 if (rc_vid.r > rc_bound.r - rc_bound.l)
654 rc_vid.r = rc_bound.r - rc_bound.l;
655 rc_vid.b = (rc_vid.r << 16) / aspect_vid;
657 /* else already fits */
659 else
661 /* Video proportionally narrower than bounding rectangle */
662 if (rc_vid.b > rc_bound.b - rc_bound.t)
664 rc_vid.b = rc_bound.b - rc_bound.t;
665 rc_vid.r = (aspect_vid * rc_vid.b) >> 16;
667 /* else already fits */
670 /* Even width and height >= 2 */
671 rc_vid.r = (rc_vid.r < 2) ? 2 : (rc_vid.r & ~1);
672 rc_vid.b = (rc_vid.b < 2) ? 2 : (rc_vid.b & ~1);
674 /* Center display in bounding rectangle */
675 rc_vid.l = ((rc_bound.l + rc_bound.r) - rc_vid.r) / 2;
676 rc_vid.r += rc_vid.l;
678 rc_vid.t = ((rc_bound.t + rc_bound.b) - rc_vid.b) / 2;
679 rc_vid.b += rc_vid.t;
681 DEBUGF("rc_vid: %d, %d, %d, %d\n", rc_vid.l, rc_vid.t,
682 rc_vid.r, rc_vid.b);
684 #ifndef HAVE_LCD_COLOR
685 stream_gray_show(true);
686 #endif
688 while (slider_state < state9)
690 mpeg_menu_sysevent_clear();
691 button = tmo == TIMEOUT_BLOCK ?
692 rb->button_get(true) : rb->button_get_w_tmo(tmo);
694 button = mpeg_menu_sysevent_callback(button, NULL);
696 switch (button)
698 case BUTTON_NONE:
699 break;
701 /* Coarse (1 minute) control */
702 case MPEG_START_TIME_DOWN:
703 case MPEG_START_TIME_DOWN | BUTTON_REPEAT:
704 #ifdef MPEG_START_TIME_RC_DOWN
705 case MPEG_START_TIME_RC_DOWN:
706 case MPEG_START_TIME_RC_DOWN | BUTTON_REPEAT:
707 #endif
708 resume_time = increment_time(resume_time, -60*TS_SECOND, duration);
709 slider_state = state0;
710 break;
712 case MPEG_START_TIME_UP:
713 case MPEG_START_TIME_UP | BUTTON_REPEAT:
714 #ifdef MPEG_START_TIME_RC_UP
715 case MPEG_START_TIME_RC_UP:
716 case MPEG_START_TIME_RC_UP | BUTTON_REPEAT:
717 #endif
718 resume_time = increment_time(resume_time, 60*TS_SECOND, duration);
719 slider_state = state0;
720 break;
722 /* Fine (1 second) control */
723 case MPEG_START_TIME_LEFT:
724 case MPEG_START_TIME_LEFT | BUTTON_REPEAT:
725 #ifdef MPEG_START_TIME_RC_LEFT
726 case MPEG_START_TIME_RC_LEFT:
727 case MPEG_START_TIME_RC_LEFT | BUTTON_REPEAT:
728 #endif
729 #ifdef MPEG_START_TIME_SCROLL_UP
730 case MPEG_START_TIME_SCROLL_UP:
731 case MPEG_START_TIME_SCROLL_UP | BUTTON_REPEAT:
732 #endif
733 resume_time = increment_time(resume_time, -TS_SECOND, duration);
734 slider_state = state0;
735 break;
737 case MPEG_START_TIME_RIGHT:
738 case MPEG_START_TIME_RIGHT | BUTTON_REPEAT:
739 #ifdef MPEG_START_TIME_RC_RIGHT
740 case MPEG_START_TIME_RC_RIGHT:
741 case MPEG_START_TIME_RC_RIGHT | BUTTON_REPEAT:
742 #endif
743 #ifdef MPEG_START_TIME_SCROLL_DOWN
744 case MPEG_START_TIME_SCROLL_DOWN:
745 case MPEG_START_TIME_SCROLL_DOWN | BUTTON_REPEAT:
746 #endif
747 resume_time = increment_time(resume_time, TS_SECOND, duration);
748 slider_state = state0;
749 break;
751 case MPEG_START_TIME_SELECT:
752 #ifdef MPEG_START_TIME_RC_SELECT
753 case MPEG_START_TIME_RC_SELECT:
754 #endif
755 settings.resume_time = resume_time;
756 button = MPEG_START_SEEK;
757 slider_state = state9;
758 break;
760 case MPEG_START_TIME_EXIT:
761 #ifdef MPEG_START_TIME_RC_EXIT
762 case MPEG_START_TIME_RC_EXIT:
763 #endif
764 button = MPEG_START_EXIT;
765 slider_state = state9;
766 break;
768 case ACTION_STD_CANCEL:
769 button = MPEG_START_QUIT;
770 slider_state = state9;
771 break;
773 #ifdef HAVE_LCD_ENABLE
774 case LCD_ENABLE_EVENT_0:
775 if (slider_state == state2)
776 display_thumb_image(&rc_vid);
777 continue;
778 #endif
780 default:
781 rb->default_event_handler(button);
782 rb->yield();
783 continue;
786 switch (slider_state)
788 case state0:
789 trigger_cpu_boost();
790 stream_seek(resume_time, SEEK_SET);
791 show_loading(&rc_bound);
792 draw_slider(duration, resume_time, NULL);
793 slider_state = state1;
794 tmo = THUMB_DELAY;
795 break;
796 case state1:
797 display_thumb_image(&rc_vid);
798 slider_state = state2;
799 case state2:
800 cancel_cpu_boost();
801 tmo = TIMEOUT_BLOCK;
802 default:
803 break;
806 rb->yield();
809 #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
810 rb->lcd_activation_set_hook(NULL);
811 #endif
812 #ifndef HAVE_LCD_COLOR
813 stream_gray_show(false);
814 grey_clear_display();
815 grey_update();
816 #endif
818 cancel_cpu_boost();
820 return button;
823 static int show_start_menu(uint32_t duration)
825 int selected = 0;
826 int result = 0;
827 bool menu_quit = false;
829 /* add the resume time to the menu display */
830 static char resume_str[32];
831 char hms_str[32];
832 struct hms hms;
834 MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_menu_sysevent_callback,
835 "Play from beginning", resume_str, "Set start time",
836 "Settings", "Quit mpegplayer");
838 ts_to_hms(settings.resume_time, &hms);
839 hms_format(hms_str, sizeof(hms_str), &hms);
840 rb->snprintf(resume_str, sizeof (resume_str),
841 "Resume at: %s", hms_str);
843 rb->button_clear_queue();
845 while (!menu_quit)
847 mpeg_menu_sysevent_clear();
848 result = rb->do_menu(&menu, &selected, NULL, false);
850 switch (result)
852 case MPEG_START_RESTART:
853 settings.resume_time = 0;
854 menu_quit = true;
855 break;
857 case MPEG_START_RESUME:
858 menu_quit = true;
859 break;
861 case MPEG_START_SEEK:
862 if (!stream_can_seek())
864 rb->splash(HZ, "Unavailable");
865 break;
868 result = get_start_time(duration);
870 if (result != MPEG_START_EXIT)
871 menu_quit = true;
872 break;
874 case MPEG_START_SETTINGS:
875 mpeg_settings();
876 break;
878 default:
879 result = MPEG_START_QUIT;
880 menu_quit = true;
881 break;
884 if (mpeg_menu_sysevent() != 0)
886 result = MPEG_START_QUIT;
887 menu_quit = true;
891 rb->lcd_clear_display();
892 rb->lcd_update();
894 return result;
897 /* Return the desired resume action */
898 int mpeg_start_menu(uint32_t duration)
900 mpeg_menu_sysevent_clear();
902 switch (settings.resume_options)
904 case MPEG_RESUME_MENU_IF_INCOMPLETE:
905 if (!stream_can_seek() || settings.resume_time == 0)
907 case MPEG_RESUME_RESTART:
908 settings.resume_time = 0;
909 return MPEG_START_RESTART;
911 default:
912 case MPEG_RESUME_MENU_ALWAYS:
913 return show_start_menu(duration);
914 case MPEG_RESUME_ALWAYS:
915 return MPEG_START_SEEK;
919 int mpeg_menu(void)
921 int result;
923 MENUITEM_STRINGLIST(menu, "Mpegplayer Menu", mpeg_menu_sysevent_callback,
924 "Settings", "Resume playback", "Quit mpegplayer");
926 rb->button_clear_queue();
928 mpeg_menu_sysevent_clear();
930 result = rb->do_menu(&menu, NULL, NULL, false);
932 switch (result)
934 case MPEG_MENU_SETTINGS:
935 mpeg_settings();
936 break;
938 case MPEG_MENU_RESUME:
939 break;
941 case MPEG_MENU_QUIT:
942 break;
944 default:
945 break;
948 if (mpeg_menu_sysevent() != 0)
949 result = MPEG_MENU_QUIT;
951 rb->lcd_clear_display();
952 rb->lcd_update();
954 return result;
957 /** MPEG Menu **/
958 static void display_options(void)
960 int selected = 0;
961 int result;
962 bool menu_quit = false;
964 MENUITEM_STRINGLIST(menu, "Display Options", mpeg_menu_sysevent_callback,
965 #if MPEG_OPTION_DITHERING_ENABLED
966 "Dithering",
967 #endif
968 "Display FPS", "Limit FPS", "Skip frames",
969 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
970 "Backlight brightness",
971 #endif
974 rb->button_clear_queue();
976 while (!menu_quit)
978 mpeg_menu_sysevent_clear();
979 result = rb->do_menu(&menu, &selected, NULL, false);
981 switch (result)
983 #if MPEG_OPTION_DITHERING_ENABLED
984 case MPEG_OPTION_DITHERING:
985 result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0;
986 mpeg_set_option("Dithering", &result, INT, noyes, 2, NULL);
987 settings.displayoptions =
988 (settings.displayoptions & ~LCD_YUV_DITHER)
989 | ((result != 0) ? LCD_YUV_DITHER : 0);
990 rb->lcd_yuv_set_options(settings.displayoptions);
991 break;
992 #endif /* MPEG_OPTION_DITHERING_ENABLED */
994 case MPEG_OPTION_DISPLAY_FPS:
995 mpeg_set_option("Display FPS", &settings.showfps, INT,
996 noyes, 2, NULL);
997 break;
999 case MPEG_OPTION_LIMIT_FPS:
1000 mpeg_set_option("Limit FPS", &settings.limitfps, INT,
1001 noyes, 2, NULL);
1002 break;
1004 case MPEG_OPTION_SKIP_FRAMES:
1005 mpeg_set_option("Skip frames", &settings.skipframes, INT,
1006 noyes, 2, NULL);
1007 break;
1009 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1010 case MPEG_OPTION_BACKLIGHT_BRIGHTNESS:
1011 result = settings.backlight_brightness;
1012 mpeg_backlight_update_brightness(result);
1013 mpeg_set_int("Backlight brightness", NULL, -1, &result,
1014 backlight_brightness_function, 1, -1,
1015 MAX_BRIGHTNESS_SETTING - MIN_BRIGHTNESS_SETTING,
1016 backlight_brightness_formatter);
1017 settings.backlight_brightness = result;
1018 mpeg_backlight_update_brightness(-1);
1019 break;
1020 #endif /* HAVE_BACKLIGHT_BRIGHTNESS */
1022 default:
1023 menu_quit = true;
1024 break;
1027 if (mpeg_menu_sysevent() != 0)
1028 menu_quit = true;
1032 static void audio_options(void)
1034 int selected = 0;
1035 int result;
1036 bool menu_quit = false;
1038 MENUITEM_STRINGLIST(menu, "Audio Options", mpeg_menu_sysevent_callback,
1039 "Tone Controls", "Channel Modes", "Crossfeed",
1040 "Equalizer", "Dithering");
1042 rb->button_clear_queue();
1044 while (!menu_quit)
1046 mpeg_menu_sysevent_clear();
1047 result = rb->do_menu(&menu, &selected, NULL, false);
1049 switch (result)
1051 case MPEG_AUDIO_TONE_CONTROLS:
1052 mpeg_set_option("Tone Controls", &settings.tone_controls, INT,
1053 globaloff, 2, NULL);
1054 sync_audio_setting(result, false);
1055 break;
1057 case MPEG_AUDIO_CHANNEL_MODES:
1058 mpeg_set_option("Channel Modes", &settings.channel_modes,
1059 INT, globaloff, 2, NULL);
1060 sync_audio_setting(result, false);
1061 break;
1063 case MPEG_AUDIO_CROSSFEED:
1064 mpeg_set_option("Crossfeed", &settings.crossfeed, INT,
1065 globaloff, 2, NULL);
1066 sync_audio_setting(result, false);
1067 break;
1069 case MPEG_AUDIO_EQUALIZER:
1070 mpeg_set_option("Equalizer", &settings.equalizer, INT,
1071 globaloff, 2, NULL);
1072 sync_audio_setting(result, false);
1073 break;
1075 case MPEG_AUDIO_DITHERING:
1076 mpeg_set_option("Dithering", &settings.dithering, INT,
1077 globaloff, 2, NULL);
1078 sync_audio_setting(result, false);
1079 break;
1081 default:
1082 menu_quit = true;
1083 break;
1086 if (mpeg_menu_sysevent() != 0)
1087 menu_quit = true;
1091 static void resume_options(void)
1093 static const struct opt_items items[MPEG_RESUME_NUM_OPTIONS] = {
1094 [MPEG_RESUME_MENU_ALWAYS] =
1095 { "Start menu", -1 },
1096 [MPEG_RESUME_MENU_IF_INCOMPLETE] =
1097 { "Start menu if not completed", -1 },
1098 [MPEG_RESUME_ALWAYS] =
1099 { "Resume automatically", -1 },
1100 [MPEG_RESUME_RESTART] =
1101 { "Play from beginning", -1 },
1104 mpeg_set_option("Resume Options", &settings.resume_options,
1105 INT, items, MPEG_RESUME_NUM_OPTIONS, NULL);
1108 static void clear_resume_count(void)
1110 configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config),
1111 SETTINGS_VERSION);
1113 settings.resume_count = 0;
1115 /* add this place holder so the count is above resume entries */
1116 configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
1119 static void mpeg_settings(void)
1121 int selected = 0;
1122 int result;
1123 bool menu_quit = false;
1124 static char clear_str[32];
1126 MENUITEM_STRINGLIST(menu, "Settings", mpeg_menu_sysevent_callback,
1127 "Display Options", "Audio Options",
1128 "Resume Options", clear_str);
1130 rb->button_clear_queue();
1132 while (!menu_quit)
1134 mpeg_menu_sysevent_clear();
1136 /* Format and add resume option to the menu display */
1137 rb->snprintf(clear_str, sizeof(clear_str),
1138 "Clear all resumes: %u", settings.resume_count);
1140 result = rb->do_menu(&menu, &selected, NULL, false);
1142 switch (result)
1144 case MPEG_SETTING_DISPLAY_SETTINGS:
1145 display_options();
1146 break;
1148 case MPEG_SETTING_AUDIO_SETTINGS:
1149 audio_options();
1150 break;
1152 case MPEG_SETTING_ENABLE_START_MENU:
1153 resume_options();
1154 break;
1156 case MPEG_SETTING_CLEAR_RESUMES:
1157 clear_resume_count();
1158 break;
1160 default:
1161 menu_quit = true;
1162 break;
1165 if (mpeg_menu_sysevent() != 0)
1166 menu_quit = true;
1170 void init_settings(const char* filename)
1172 /* Set the default settings */
1173 settings.showfps = 0; /* Do not show FPS */
1174 settings.limitfps = 1; /* Limit FPS */
1175 settings.skipframes = 1; /* Skip frames */
1176 settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */
1177 settings.resume_count = -1;
1178 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1179 settings.backlight_brightness = -1; /* Use default setting */
1180 #endif
1181 #if MPEG_OPTION_DITHERING_ENABLED
1182 settings.displayoptions = 0; /* No visual effects */
1183 #endif
1184 settings.tone_controls = false;
1185 settings.channel_modes = false;
1186 settings.crossfeed = false;
1187 settings.equalizer = false;
1188 settings.dithering = false;
1190 if (configfile_load(SETTINGS_FILENAME, config,
1191 sizeof(config)/sizeof(*config),
1192 SETTINGS_MIN_VERSION) < 0)
1194 /* Generate a new config file with default values */
1195 configfile_save(SETTINGS_FILENAME, config,
1196 sizeof(config)/sizeof(*config),
1197 SETTINGS_VERSION);
1200 #if MPEG_OPTION_DITHERING_ENABLED
1201 if ((settings.displayoptions =
1202 configfile_get_value(SETTINGS_FILENAME, "Display options")) < 0)
1204 configfile_update_entry(SETTINGS_FILENAME, "Display options",
1205 (settings.displayoptions=0));
1207 rb->lcd_yuv_set_options(settings.displayoptions);
1208 #endif
1210 if (settings.resume_count < 0)
1212 settings.resume_count = 0;
1213 configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
1216 rb->snprintf(settings.resume_filename, MAX_PATH, "%s", filename);
1218 /* get the resume time for the current mpeg if it exist */
1219 if ((settings.resume_time = configfile_get_value
1220 (SETTINGS_FILENAME, filename)) < 0)
1222 settings.resume_time = 0;
1225 /* Set our audio options */
1226 sync_audio_settings(false);
1229 void save_settings(void)
1231 configfile_update_entry(SETTINGS_FILENAME, "Show FPS",
1232 settings.showfps);
1233 configfile_update_entry(SETTINGS_FILENAME, "Limit FPS",
1234 settings.limitfps);
1235 configfile_update_entry(SETTINGS_FILENAME, "Skip frames",
1236 settings.skipframes);
1237 configfile_update_entry(SETTINGS_FILENAME, "Resume options",
1238 settings.resume_options);
1240 /* If this was a new resume entry then update the total resume count */
1241 if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename,
1242 settings.resume_time) == 0)
1244 configfile_update_entry(SETTINGS_FILENAME, "Resume count",
1245 ++settings.resume_count);
1248 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1249 configfile_update_entry(SETTINGS_FILENAME, "Backlight brightness",
1250 settings.backlight_brightness);
1251 #endif
1253 #if MPEG_OPTION_DITHERING_ENABLED
1254 configfile_update_entry(SETTINGS_FILENAME, "Display options",
1255 settings.displayoptions);
1256 #endif
1257 configfile_update_entry(SETTINGS_FILENAME, "Tone controls",
1258 settings.tone_controls);
1259 configfile_update_entry(SETTINGS_FILENAME, "Channel modes",
1260 settings.channel_modes);
1261 configfile_update_entry(SETTINGS_FILENAME, "Crossfeed",
1262 settings.crossfeed);
1263 configfile_update_entry(SETTINGS_FILENAME, "Equalizer",
1264 settings.equalizer);
1265 configfile_update_entry(SETTINGS_FILENAME, "Dithering",
1266 settings.dithering);
1268 /* Restore audio options */
1269 sync_audio_settings(true);