mpegplayer: Make playback engine fully seekable and frame-accurate and split into...
[Rockbox.git] / apps / plugins / mpegplayer / mpeg_settings.c
blob7336507aaa34c093f19a05bd8d967dd08ffcbe8d
1 #include "plugin.h"
2 #include "lib/configfile.h"
3 #include "lib/oldmenuapi.h"
5 #include "mpegplayer.h"
6 #include "mpeg_settings.h"
8 struct mpeg_settings settings;
10 #define SETTINGS_VERSION 2
11 #define SETTINGS_MIN_VERSION 1
12 #define SETTINGS_FILENAME "mpegplayer.cfg"
14 #define THUMB_DELAY (75*HZ/100)
16 /* button definitions */
17 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
18 (CONFIG_KEYPAD == IRIVER_H300_PAD)
19 #define MPEG_SELECT BUTTON_ON
20 #define MPEG_RIGHT BUTTON_RIGHT
21 #define MPEG_LEFT BUTTON_LEFT
22 #define MPEG_UP BUTTON_UP
23 #define MPEG_DOWN BUTTON_DOWN
24 #define MPEG_EXIT BUTTON_OFF
26 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
27 #define MPEG_SELECT BUTTON_PLAY
28 #define MPEG_RIGHT BUTTON_RIGHT
29 #define MPEG_LEFT BUTTON_LEFT
30 #define MPEG_UP BUTTON_UP
31 #define MPEG_DOWN BUTTON_DOWN
32 #define MPEG_EXIT BUTTON_POWER
34 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
35 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
36 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
37 #define MPEG_SELECT BUTTON_SELECT
38 #define MPEG_RIGHT BUTTON_RIGHT
39 #define MPEG_LEFT BUTTON_LEFT
40 #define MPEG_UP BUTTON_SCROLL_FWD
41 #define MPEG_DOWN BUTTON_SCROLL_BACK
42 #define MPEG_EXIT BUTTON_MENU
44 #elif CONFIG_KEYPAD == GIGABEAT_PAD
45 #define MPEG_SELECT BUTTON_SELECT
46 #define MPEG_LEFT BUTTON_LEFT
47 #define MPEG_RIGHT BUTTON_RIGHT
48 #define MPEG_UP BUTTON_UP
49 #define MPEG_DOWN BUTTON_DOWN
50 #define MPEG_SCROLL_DOWN BUTTON_VOL_DOWN
51 #define MPEG_SCROLL_UP BUTTON_VOL_UP
52 #define MPEG_EXIT BUTTON_POWER
54 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
55 #define MPEG_SELECT BUTTON_PLAY
56 #define MPEG_LEFT BUTTON_LEFT
57 #define MPEG_RIGHT BUTTON_RIGHT
58 #define MPEG_UP BUTTON_SCROLL_UP
59 #define MPEG_DOWN BUTTON_SCROLL_DOWN
60 #define MPEG_EXIT BUTTON_POWER
62 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
63 #define MPEG_SELECT BUTTON_SELECT
64 #define MPEG_SCROLL_UP BUTTON_SCROLL_UP
65 #define MPEG_SCROLL_DOWN BUTTON_SCROLL_DOWN
66 #define MPEG_LEFT BUTTON_LEFT
67 #define MPEG_RIGHT BUTTON_RIGHT
68 #define MPEG_UP BUTTON_UP
69 #define MPEG_DOWN BUTTON_DOWN
70 #define MPEG_EXIT BUTTON_POWER
72 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
73 #define MPEG_SELECT BUTTON_SELECT
74 #define MPEG_SCROLL_UP BUTTON_VOL_UP
75 #define MPEG_SCROLL_DOWN BUTTON_VOL_DOWN
76 #define MPEG_LEFT BUTTON_LEFT
77 #define MPEG_RIGHT BUTTON_RIGHT
78 #define MPEG_UP BUTTON_UP
79 #define MPEG_DOWN BUTTON_DOWN
80 #define MPEG_EXIT BUTTON_POWER
82 #elif CONFIG_KEYPAD == MROBE500_PAD
83 #define MPEG_SELECT BUTTON_RC_HEART
84 #define MPEG_SCROLL_UP BUTTON_RC_VOL_UP
85 #define MPEG_SCROLL_DOWN BUTTON_RC_VOL_DOWN
86 #define MPEG_LEFT BUTTON_LEFT
87 #define MPEG_RIGHT BUTTON_RIGHT
88 #define MPEG_UP BUTTON_RC_PLAY
89 #define MPEG_DOWN BUTTON_RC_DOWN
90 #define MPEG_EXIT BUTTON_POWER
92 #else
93 #error MPEGPLAYER: Unsupported keypad
94 #endif
96 static struct configdata config[] =
98 {TYPE_INT, 0, 2, &settings.showfps, "Show FPS", NULL, NULL},
99 {TYPE_INT, 0, 2, &settings.limitfps, "Limit FPS", NULL, NULL},
100 {TYPE_INT, 0, 2, &settings.skipframes, "Skip frames", NULL, NULL},
101 {TYPE_INT, 0, INT_MAX, &settings.resume_count, "Resume count",
102 NULL, NULL},
103 {TYPE_INT, 0, 2, &settings.enable_start_menu, "Enable start menu",
104 NULL, NULL},
105 #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200)
106 {TYPE_INT, 0, INT_MAX, &settings.displayoptions, "Display options",
107 NULL, NULL},
108 #endif
111 static const struct opt_items noyes[2] = {
112 { "No", -1 },
113 { "Yes", -1 },
116 static const struct opt_items enabledisable[2] = {
117 { "Disable", -1 },
118 { "Enable", -1 },
121 static void display_options(void)
123 int result;
124 int menu_id;
125 int options_quit = 0;
127 static const struct menu_item items[] = {
128 #if MPEG_OPTION_DITHERING_ENABLED
129 [MPEG_OPTION_DITHERING] =
130 { "Dithering", NULL },
131 #endif
132 [MPEG_OPTION_DISPLAY_FPS] =
133 { "Display FPS", NULL },
134 [MPEG_OPTION_LIMIT_FPS] =
135 { "Limit FPS", NULL },
136 [MPEG_OPTION_SKIP_FRAMES] =
137 { "Skip frames", NULL },
140 menu_id = menu_init(rb, items, ARRAYLEN(items),
141 NULL, NULL, NULL, NULL);
143 rb->button_clear_queue();
145 while(options_quit == 0)
147 result = menu_show(menu_id);
149 switch (result)
151 #if MPEG_OPTION_DITHERING_ENABLED
152 case MPEG_OPTION_DITHERING:
153 result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0;
154 rb->set_option("Dithering", &result, INT, noyes, 2, NULL);
155 settings.displayoptions = (settings.displayoptions & ~LCD_YUV_DITHER)
156 | ((result != 0) ? LCD_YUV_DITHER : 0);
157 rb->lcd_yuv_set_options(settings.displayoptions);
158 break;
159 #endif /* MPEG_OPTION_DITHERING_ENABLED */
160 case MPEG_OPTION_DISPLAY_FPS:
161 rb->set_option("Display FPS",&settings.showfps,INT,
162 noyes, 2, NULL);
163 break;
164 case MPEG_OPTION_LIMIT_FPS:
165 rb->set_option("Limit FPS",&settings.limitfps,INT,
166 noyes, 2, NULL);
167 break;
168 case MPEG_OPTION_SKIP_FRAMES:
169 rb->set_option("Skip frames",&settings.skipframes,INT,
170 noyes, 2, NULL);
171 break;
172 default:
173 options_quit=1;
174 break;
178 menu_exit(menu_id);
181 static void show_loading(struct vo_rect *rc)
183 int oldmode;
184 #ifndef HAVE_LCD_COLOR
185 stream_gray_show(false);
186 #endif
187 oldmode = rb->lcd_get_drawmode();
188 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
189 rb->lcd_fillrect(rc->l-1, rc->t-1, rc->r - rc->l + 2, rc->b - rc->t + 2);
190 rb->lcd_set_drawmode(oldmode);
191 rb->splash(0, "Loading...");
194 void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc)
196 #define SLIDER_WIDTH (LCD_WIDTH-SLIDER_LMARGIN-SLIDER_RMARGIN)
197 #define SLIDER_X SLIDER_LMARGIN
198 #define SLIDER_Y (LCD_HEIGHT-SLIDER_HEIGHT-SLIDER_BMARGIN)
199 #define SLIDER_HEIGHT 8
200 #define SLIDER_TEXTMARGIN 1
201 #define SLIDER_LMARGIN 1
202 #define SLIDER_RMARGIN 1
203 #define SLIDER_TMARGIN 1
204 #define SLIDER_BMARGIN 1
205 #define SCREEN_MARGIN 1
207 struct hms hms;
208 char str[32];
209 int text_w, text_h, text_y;
211 /* Put positition on left */
212 ts_to_hms(pos, &hms);
213 hms_format(str, sizeof(str), &hms);
214 rb->lcd_getstringsize(str, NULL, &text_h);
215 text_y = SLIDER_Y - SLIDER_TEXTMARGIN - text_h;
217 if (rc == NULL)
219 int oldmode = rb->lcd_get_drawmode();
220 rb->lcd_set_drawmode(DRMODE_BG | DRMODE_INVERSEVID);
221 rb->lcd_fillrect(SLIDER_X, text_y, SLIDER_WIDTH,
222 LCD_HEIGHT - SLIDER_BMARGIN - text_y
223 - SLIDER_TMARGIN);
224 rb->lcd_set_drawmode(oldmode);
226 rb->lcd_putsxy(SLIDER_X, text_y, str);
228 /* Put duration on right */
229 ts_to_hms(range, &hms);
230 hms_format(str, sizeof(str), &hms);
231 rb->lcd_getstringsize(str, &text_w, NULL);
233 rb->lcd_putsxy(SLIDER_X + SLIDER_WIDTH - text_w, text_y, str);
235 /* Draw slider */
236 rb->lcd_drawrect(SLIDER_X, SLIDER_Y, SLIDER_WIDTH, SLIDER_HEIGHT);
237 rb->lcd_fillrect(SLIDER_X, SLIDER_Y,
238 muldiv_uint32(pos, SLIDER_WIDTH, range),
239 SLIDER_HEIGHT);
241 /* Update screen */
242 rb->lcd_update_rect(SLIDER_X, text_y - SLIDER_TMARGIN, SLIDER_WIDTH,
243 LCD_HEIGHT - SLIDER_BMARGIN - text_y + SLIDER_TEXTMARGIN);
245 else
247 /* Just return slider rectangle */
248 rc->l = SLIDER_X;
249 rc->t = text_y - SLIDER_TMARGIN;
250 rc->r = rc->l + SLIDER_WIDTH;
251 rc->b = rc->t + LCD_HEIGHT - SLIDER_BMARGIN - text_y;
255 bool display_thumb_image(const struct vo_rect *rc)
257 if (!stream_display_thumb(rc))
259 rb->splash(0, "Frame not available");
260 return false;
263 #ifdef HAVE_LCD_COLOR
264 /* Draw a raised border around the frame */
265 int oldcolor = rb->lcd_get_foreground();
266 rb->lcd_set_foreground(LCD_LIGHTGRAY);
268 rb->lcd_hline(rc->l-1, rc->r-1, rc->t-1);
269 rb->lcd_vline(rc->l-1, rc->t, rc->b-1);
271 rb->lcd_set_foreground(LCD_DARKGRAY);
273 rb->lcd_hline(rc->l-1, rc->r, rc->b);
274 rb->lcd_vline(rc->r, rc->t-1, rc->b);
276 rb->lcd_set_foreground(oldcolor);
278 rb->lcd_update_rect(rc->l-1, rc->t-1, rc->r - rc->l + 2, 1);
279 rb->lcd_update_rect(rc->l-1, rc->t, 1, rc->b - rc->t);
280 rb->lcd_update_rect(rc->l-1, rc->b, rc->r - rc->l + 2, 1);
281 rb->lcd_update_rect(rc->r, rc->t, 1, rc->b - rc->t);
282 #else
283 /* Just show the thumbnail */
284 stream_gray_show(true);
285 #endif
287 return true;
290 /* Add an amount to the specified time - with saturation */
291 uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range)
293 if (amount < 0)
295 uint32_t off = -amount;
296 if (range > off && val >= off)
297 val -= off;
298 else
299 val = 0;
301 else if (amount > 0)
303 uint32_t off = amount;
304 if (range > off && val <= range - off)
305 val += off;
306 else
307 val = range;
310 return val;
313 int get_start_time(uint32_t duration)
315 int button = 0;
316 int tmo = TIMEOUT_NOBLOCK;
317 uint32_t resume_time = settings.resume_time;
318 struct vo_rect rc_vid, rc_bound;
319 uint32_t aspect_vid, aspect_bound;
321 enum state_enum slider_state = state0;
323 rb->lcd_clear_display();
324 rb->lcd_update();
326 draw_slider(0, 100, &rc_bound);
327 rc_bound.b = rc_bound.t - SLIDER_TMARGIN;
328 #ifdef HAVE_LCD_COLOR
329 rc_bound.t = SCREEN_MARGIN;
330 #else
331 rc_bound.t = 0;
332 rc_bound.l = 0;
333 rc_bound.r = LCD_WIDTH;
334 #endif
336 DEBUGF("rc_bound: %d, %d, %d, %d\n", rc_bound.l, rc_bound.t,
337 rc_bound.r, rc_bound.b);
339 rc_vid.l = rc_vid.t = 0;
340 if (!stream_vo_get_size((struct vo_ext *)&rc_vid.r))
342 /* Can't get size - fill whole thing */
343 rc_vid.r = rc_bound.r - rc_bound.l;
344 rc_vid.b = rc_bound.b - rc_bound.t;
347 #if !defined (HAVE_LCD_COLOR)
348 #if LCD_PIXELFORMAT == VERTICAL_PACKING
349 rc_bound.b &= ~7; /* Align bottom edge */
350 #endif
351 #endif
353 /* Get aspect ratio of bounding rectangle and video in u16.16 */
354 aspect_bound = ((rc_bound.r - rc_bound.l) << 16) /
355 (rc_bound.b - rc_bound.t);
357 DEBUGF("aspect_bound: %ld.%02ld\n", aspect_bound >> 16,
358 100*(aspect_bound & 0xffff) >> 16);
360 aspect_vid = (rc_vid.r << 16) / rc_vid.b;
362 DEBUGF("aspect_vid: %ld.%02ld\n", aspect_vid >> 16,
363 100*(aspect_vid & 0xffff) >> 16);
365 if (aspect_vid >= aspect_bound)
367 /* Video proportionally wider than or same as bounding rectangle */
368 if (rc_vid.r > rc_bound.r - rc_bound.l)
370 rc_vid.r = rc_bound.r - rc_bound.l;
371 rc_vid.b = (rc_vid.r << 16) / aspect_vid;
373 /* else already fits */
375 else
377 /* Video proportionally narrower than bounding rectangle */
378 if (rc_vid.b > rc_bound.b - rc_bound.t)
380 rc_vid.b = rc_bound.b - rc_bound.t;
381 rc_vid.r = (aspect_vid * rc_vid.b) >> 16;
383 /* else already fits */
386 /* Even width and height >= 2 */
387 rc_vid.r = (rc_vid.r < 2) ? 2 : (rc_vid.r & ~1);
388 rc_vid.b = (rc_vid.b < 2) ? 2 : (rc_vid.b & ~1);
390 /* Center display in bounding rectangle */
391 rc_vid.l = ((rc_bound.l + rc_bound.r) - rc_vid.r) / 2;
392 rc_vid.r += rc_vid.l;
394 rc_vid.t = ((rc_bound.t + rc_bound.b) - rc_vid.b) / 2;
395 rc_vid.b += rc_vid.t;
397 DEBUGF("rc_vid: %d, %d, %d, %d\n", rc_vid.l, rc_vid.t,
398 rc_vid.r, rc_vid.b);
400 #ifndef HAVE_LCD_COLOR
401 /* Set gray overlay to the bounding rectangle */
402 stream_set_gray_rect(&rc_bound);
403 #endif
405 while(slider_state < state9)
407 button = tmo == TIMEOUT_BLOCK ?
408 rb->button_get(true) : rb->button_get_w_tmo(tmo);
410 switch (button)
412 case BUTTON_NONE:
413 break;
415 /* Coarse (1 minute) control */
416 case MPEG_DOWN:
417 case MPEG_DOWN | BUTTON_REPEAT:
418 resume_time = increment_time(resume_time, -60*TS_SECOND, duration);
419 slider_state = state0;
420 break;
422 case MPEG_UP:
423 case MPEG_UP | BUTTON_REPEAT:
424 resume_time = increment_time(resume_time, 60*TS_SECOND, duration);
425 slider_state = state0;
426 break;
428 /* Fine (1 second) control */
429 case MPEG_LEFT:
430 case MPEG_LEFT | BUTTON_REPEAT:
431 #ifdef MPEG_SCROLL_UP
432 case MPEG_SCROLL_UP:
433 case MPEG_SCROLL_UP | BUTTON_REPEAT:
434 #endif
435 resume_time = increment_time(resume_time, -TS_SECOND, duration);
436 slider_state = state0;
437 break;
439 case MPEG_RIGHT:
440 case MPEG_RIGHT | BUTTON_REPEAT:
441 #ifdef MPEG_SCROLL_DOWN
442 case MPEG_SCROLL_DOWN:
443 case MPEG_SCROLL_DOWN | BUTTON_REPEAT:
444 #endif
445 resume_time = increment_time(resume_time, TS_SECOND, duration);
446 slider_state = state0;
447 break;
449 case MPEG_SELECT:
450 settings.resume_time = resume_time;
451 case MPEG_EXIT:
452 slider_state = state9;
453 break;
455 case SYS_USB_CONNECTED:
456 slider_state = state9;
457 #ifndef HAVE_LCD_COLOR
458 stream_gray_show(false);
459 #endif
460 cancel_cpu_boost();
461 default:
462 rb->default_event_handler(button);
463 rb->yield();
464 continue;
467 switch(slider_state)
469 case state0:
470 trigger_cpu_boost();
471 stream_seek(resume_time, SEEK_SET);
472 show_loading(&rc_bound);
473 draw_slider(duration, resume_time, NULL);
474 slider_state = state1;
475 tmo = THUMB_DELAY;
476 break;
477 case state1:
478 display_thumb_image(&rc_vid);
479 slider_state = state2;
480 case state2:
481 case state9:
482 cancel_cpu_boost();
483 tmo = TIMEOUT_BLOCK;
484 default:
485 break;
489 #ifndef HAVE_LCD_COLOR
490 /* Restore gray overlay dimensions */
491 stream_gray_show(false);
492 rc_bound.b = LCD_HEIGHT;
493 stream_set_gray_rect(&rc_bound);
494 #endif
496 cancel_cpu_boost();
498 return button;
501 enum mpeg_start_id mpeg_start_menu(uint32_t duration)
503 int menu_id;
504 int result = 0;
505 int menu_quit = 0;
507 /* add the resume time to the menu display */
508 char resume_str[32];
509 char hms_str[32];
510 struct hms hms;
512 ts_to_hms(settings.resume_time, &hms);
513 hms_format(hms_str, sizeof(hms_str), &hms);
515 if (settings.enable_start_menu == 0)
517 rb->snprintf(resume_str, sizeof(resume_str), "Yes: %s", hms_str);
519 struct opt_items resume_no_yes[2] =
521 { "No", -1 },
522 { resume_str, -1 },
524 if (settings.resume_time == 0)
525 return MPEG_START_RESTART;
527 rb->set_option("Resume", &result, INT,
528 resume_no_yes, 2, NULL);
530 if (result == 0)
532 settings.resume_time = 0;
533 return MPEG_START_RESTART;
535 else
536 return MPEG_START_RESUME;
539 rb->snprintf(resume_str, sizeof(resume_str), "Resume at: %s", hms_str);
541 struct menu_item items[] =
543 [MPEG_START_RESTART] =
544 { "Play from beginning", NULL },
545 [MPEG_START_RESUME] =
546 { resume_str, NULL },
547 [MPEG_START_SEEK] =
548 { "Set start time", NULL },
549 [MPEG_START_QUIT] =
550 { "Quit mpegplayer", NULL },
554 menu_id = menu_init(rb, items, sizeof(items) / sizeof(*items),
555 NULL, NULL, NULL, NULL);
557 rb->button_clear_queue();
559 while(menu_quit == 0)
561 result = menu_show(menu_id);
563 switch (result)
565 case MPEG_START_RESTART:
566 settings.resume_time = 0;
567 menu_quit = 1;
568 break;
569 case MPEG_START_RESUME:
570 menu_quit = 1;
571 break;
572 case MPEG_START_SEEK:
574 if (!stream_can_seek())
576 rb->splash(HZ, "Unavailable");
577 break;
580 bool vis = stream_show_vo(false);
581 if (get_start_time(duration) == MPEG_SELECT)
582 menu_quit = 1;
583 stream_show_vo(vis);
584 break;
586 case MPEG_START_QUIT:
587 menu_quit = 1;
588 break;
589 default:
590 result = MPEG_START_QUIT;
591 menu_quit = 1;
592 break;
596 menu_exit(menu_id);
598 rb->lcd_clear_display();
599 rb->lcd_update();
601 return result;
604 void clear_resume_count(void)
606 configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config),
607 SETTINGS_VERSION);
609 settings.resume_count = 0;
611 /* add this place holder so the count is above resume entries */
612 configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
615 enum mpeg_menu_id mpeg_menu(void)
617 int menu_id;
618 int result;
619 int menu_quit=0;
621 /* add the clear resume option to the menu display */
622 char clear_str[32];
623 rb->snprintf(clear_str, sizeof(clear_str),
624 "Clear all resumes: %u", settings.resume_count);
626 struct menu_item items[] = {
627 [MPEG_MENU_DISPLAY_SETTINGS] =
628 { "Display Options", NULL },
629 [MPEG_MENU_ENABLE_START_MENU] =
630 { "Start menu", NULL },
631 [MPEG_MENU_CLEAR_RESUMES] =
632 { clear_str, NULL },
633 [MPEG_MENU_QUIT] =
634 { "Quit mpegplayer", NULL },
637 menu_id = menu_init(rb, items, ARRAYLEN(items),
638 NULL, NULL, NULL, NULL);
640 rb->button_clear_queue();
642 while (menu_quit == 0)
644 result=menu_show(menu_id);
646 switch(result)
648 case MPEG_MENU_DISPLAY_SETTINGS:
649 display_options();
650 break;
651 case MPEG_MENU_ENABLE_START_MENU:
652 rb->set_option("Start menu",
653 &settings.enable_start_menu,
654 INT, enabledisable, 2, NULL);
655 break;
656 case MPEG_MENU_CLEAR_RESUMES:
657 clear_resume_count();
658 rb->snprintf(clear_str, sizeof(clear_str),
659 "Clear all resumes: %u", 0);
660 break;
661 case MPEG_MENU_QUIT:
662 default:
663 menu_quit=1;
664 if (result == MENU_ATTACHED_USB)
665 result = MPEG_MENU_QUIT;
666 break;
670 menu_exit(menu_id);
672 rb->lcd_clear_display();
673 rb->lcd_update();
675 return result;
678 void init_settings(const char* filename)
680 /* Set the default settings */
681 settings.showfps = 0; /* Do not show FPS */
682 settings.limitfps = 1; /* Limit FPS */
683 settings.skipframes = 1; /* Skip frames */
684 settings.enable_start_menu = 1; /* Enable start menu */
685 settings.resume_count = -1;
686 #if MPEG_OPTION_DITHERING_ENABLED
687 settings.displayoptions = 0; /* No visual effects */
688 #endif
690 configfile_init(rb);
692 if (configfile_load(SETTINGS_FILENAME, config,
693 sizeof(config)/sizeof(*config),
694 SETTINGS_MIN_VERSION) < 0)
696 /* Generate a new config file with default values */
697 configfile_save(SETTINGS_FILENAME, config,
698 sizeof(config)/sizeof(*config),
699 SETTINGS_VERSION);
702 #if MPEG_OPTION_DITHERING_ENABLED
703 if ((settings.displayoptions =
704 configfile_get_value(SETTINGS_FILENAME, "Display options")) < 0)
706 configfile_update_entry(SETTINGS_FILENAME, "Display options",
707 (settings.displayoptions=0));
709 rb->lcd_yuv_set_options(settings.displayoptions);
710 #endif
712 if (settings.resume_count < 0)
714 settings.resume_count = 0;
715 configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
718 rb->snprintf(settings.resume_filename, MAX_PATH, "%s", filename);
720 /* get the resume time for the current mpeg if it exist */
721 if ((settings.resume_time = configfile_get_value
722 (SETTINGS_FILENAME, filename)) < 0)
724 settings.resume_time = 0;
728 void save_settings(void)
730 configfile_update_entry(SETTINGS_FILENAME, "Show FPS",
731 settings.showfps);
732 configfile_update_entry(SETTINGS_FILENAME, "Limit FPS",
733 settings.limitfps);
734 configfile_update_entry(SETTINGS_FILENAME, "Skip frames",
735 settings.skipframes);
736 configfile_update_entry(SETTINGS_FILENAME, "Enable start menu",
737 settings.enable_start_menu);
739 /* If this was a new resume entry then update the total resume count */
740 if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename,
741 settings.resume_time) == 0)
743 configfile_update_entry(SETTINGS_FILENAME, "Resume count",
744 ++settings.resume_count);
747 #if MPEG_OPTION_DITHERING_ENABLED
748 configfile_update_entry(SETTINGS_FILENAME, "Display options",
749 settings.displayoptions);
750 #endif