1
0
Fork 0
forked from len0rd/rockbox

mpegplayer: A) Replace 'Start Menu' option with 'Resume Settings' 1) Start menu - Always show the start menu 2) Start menu if not completed - show the start menu if playback was interrupted before finishing (equivalent to the previous 'Resume No/Yes' screen) 3) Resume automatically - Always resume immediately with no prompting 4) Play from beginning - Always play file from the beginning. B) Do everything possible at this time to ensure USB connection and power down preserve the resume time. C) Add Settings menu to start menu D) Small OSD erasure drawing tweak.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16061 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2008-01-12 05:45:38 +00:00
parent 41cd44caa7
commit 29775f7bab
4 changed files with 436 additions and 279 deletions

View file

@ -7,87 +7,83 @@
struct mpeg_settings settings; struct mpeg_settings settings;
#define SETTINGS_VERSION 2
#define SETTINGS_MIN_VERSION 1
#define SETTINGS_FILENAME "mpegplayer.cfg"
#define THUMB_DELAY (75*HZ/100) #define THUMB_DELAY (75*HZ/100)
/* button definitions */ /* button definitions */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
(CONFIG_KEYPAD == IRIVER_H300_PAD) (CONFIG_KEYPAD == IRIVER_H300_PAD)
#define MPEG_SELECT BUTTON_ON #define MPEG_START_TIME_SELECT BUTTON_ON
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_UP BUTTON_UP #define MPEG_START_TIME_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN #define MPEG_START_TIME_DOWN BUTTON_DOWN
#define MPEG_EXIT BUTTON_OFF #define MPEG_START_TIME_EXIT BUTTON_OFF
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
#define MPEG_SELECT BUTTON_PLAY #define MPEG_START_TIME_SELECT BUTTON_PLAY
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_UP BUTTON_UP #define MPEG_START_TIME_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN #define MPEG_START_TIME_DOWN BUTTON_DOWN
#define MPEG_EXIT BUTTON_POWER #define MPEG_START_TIME_EXIT BUTTON_POWER
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD) (CONFIG_KEYPAD == IPOD_1G2G_PAD)
#define MPEG_SELECT BUTTON_SELECT #define MPEG_START_TIME_SELECT BUTTON_SELECT
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_UP BUTTON_SCROLL_FWD #define MPEG_START_TIME_UP BUTTON_SCROLL_FWD
#define MPEG_DOWN BUTTON_SCROLL_BACK #define MPEG_START_TIME_DOWN BUTTON_SCROLL_BACK
#define MPEG_EXIT BUTTON_MENU #define MPEG_START_TIME_EXIT BUTTON_MENU
#elif CONFIG_KEYPAD == GIGABEAT_PAD #elif CONFIG_KEYPAD == GIGABEAT_PAD
#define MPEG_SELECT BUTTON_SELECT #define MPEG_START_TIME_SELECT BUTTON_SELECT
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_UP #define MPEG_START_TIME_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN #define MPEG_START_TIME_DOWN BUTTON_DOWN
#define MPEG_SCROLL_DOWN BUTTON_VOL_DOWN #define MPEG_START_TIME_SCROLL_DOWN BUTTON_VOL_DOWN
#define MPEG_SCROLL_UP BUTTON_VOL_UP #define MPEG_START_TIME_SCROLL_UP BUTTON_VOL_UP
#define MPEG_EXIT BUTTON_POWER #define MPEG_START_TIME_EXIT BUTTON_POWER
#elif CONFIG_KEYPAD == IRIVER_H10_PAD #elif CONFIG_KEYPAD == IRIVER_H10_PAD
#define MPEG_SELECT BUTTON_PLAY #define MPEG_START_TIME_SELECT BUTTON_PLAY
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_SCROLL_UP #define MPEG_START_TIME_UP BUTTON_SCROLL_UP
#define MPEG_DOWN BUTTON_SCROLL_DOWN #define MPEG_START_TIME_DOWN BUTTON_SCROLL_DOWN
#define MPEG_EXIT BUTTON_POWER #define MPEG_START_TIME_EXIT BUTTON_POWER
#elif (CONFIG_KEYPAD == SANSA_E200_PAD) #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
#define MPEG_SELECT BUTTON_SELECT #define MPEG_START_TIME_SELECT BUTTON_SELECT
#define MPEG_SCROLL_UP BUTTON_SCROLL_BACK #define MPEG_START_TIME_SCROLL_UP BUTTON_SCROLL_BACK
#define MPEG_SCROLL_DOWN BUTTON_SCROLL_FWD #define MPEG_START_TIME_SCROLL_DOWN BUTTON_SCROLL_FWD
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_UP #define MPEG_START_TIME_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN #define MPEG_START_TIME_DOWN BUTTON_DOWN
#define MPEG_EXIT BUTTON_POWER #define MPEG_START_TIME_EXIT BUTTON_POWER
#elif (CONFIG_KEYPAD == SANSA_C200_PAD) #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
#define MPEG_SELECT BUTTON_SELECT #define MPEG_START_TIME_SELECT BUTTON_SELECT
#define MPEG_SCROLL_UP BUTTON_VOL_UP #define MPEG_START_TIME_SCROLL_UP BUTTON_VOL_UP
#define MPEG_SCROLL_DOWN BUTTON_VOL_DOWN #define MPEG_START_TIME_SCROLL_DOWN BUTTON_VOL_DOWN
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_UP #define MPEG_START_TIME_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN #define MPEG_START_TIME_DOWN BUTTON_DOWN
#define MPEG_EXIT BUTTON_POWER #define MPEG_START_TIME_EXIT BUTTON_POWER
#elif CONFIG_KEYPAD == MROBE500_PAD #elif CONFIG_KEYPAD == MROBE500_PAD
#define MPEG_SELECT BUTTON_RC_HEART #define MPEG_START_TIME_SELECT BUTTON_RC_HEART
#define MPEG_SCROLL_UP BUTTON_RC_VOL_UP #define MPEG_START_TIME_SCROLL_UP BUTTON_RC_VOL_UP
#define MPEG_SCROLL_DOWN BUTTON_RC_VOL_DOWN #define MPEG_START_TIME_SCROLL_DOWN BUTTON_RC_VOL_DOWN
#define MPEG_LEFT BUTTON_LEFT #define MPEG_START_TIME_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT #define MPEG_START_TIME_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_RC_PLAY #define MPEG_START_TIME_UP BUTTON_RC_PLAY
#define MPEG_DOWN BUTTON_RC_DOWN #define MPEG_START_TIME_DOWN BUTTON_RC_DOWN
#define MPEG_EXIT BUTTON_POWER #define MPEG_START_TIME_EXIT BUTTON_POWER
#else #else
#error MPEGPLAYER: Unsupported keypad #error MPEGPLAYER: Unsupported keypad
@ -100,8 +96,8 @@ static struct configdata config[] =
{TYPE_INT, 0, 2, &settings.skipframes, "Skip frames", NULL, NULL}, {TYPE_INT, 0, 2, &settings.skipframes, "Skip frames", NULL, NULL},
{TYPE_INT, 0, INT_MAX, &settings.resume_count, "Resume count", {TYPE_INT, 0, INT_MAX, &settings.resume_count, "Resume count",
NULL, NULL}, NULL, NULL},
{TYPE_INT, 0, 2, &settings.enable_start_menu, "Enable start menu", {TYPE_INT, 0, MPEG_RESUME_NUM_OPTIONS, &settings.resume_options,
NULL, NULL}, "Resume options", NULL, NULL},
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200)
{TYPE_INT, 0, INT_MAX, &settings.displayoptions, "Display options", {TYPE_INT, 0, INT_MAX, &settings.displayoptions, "Display options",
NULL, NULL}, NULL, NULL},
@ -118,66 +114,70 @@ static const struct opt_items enabledisable[2] = {
{ "Enable", -1 }, { "Enable", -1 },
}; };
static void display_options(void) static long mpeg_menu_sysevent_id;
void mpeg_menu_sysevent_clear(void)
{ {
int result; mpeg_menu_sysevent_id = 0;
int menu_id; }
int options_quit = 0;
static const struct menu_item items[] = { int mpeg_menu_sysevent_callback(int btn, int menu)
#if MPEG_OPTION_DITHERING_ENABLED {
[MPEG_OPTION_DITHERING] = switch (btn)
{ "Dithering", NULL },
#endif
[MPEG_OPTION_DISPLAY_FPS] =
{ "Display FPS", NULL },
[MPEG_OPTION_LIMIT_FPS] =
{ "Limit FPS", NULL },
[MPEG_OPTION_SKIP_FRAMES] =
{ "Skip frames", NULL },
};
menu_id = menu_init(rb, items, ARRAYLEN(items),
NULL, NULL, NULL, NULL);
rb->button_clear_queue();
while(options_quit == 0)
{ {
result = menu_show(menu_id); case SYS_USB_CONNECTED:
case SYS_POWEROFF:
switch (result) mpeg_menu_sysevent_id = btn;
{ return ACTION_STD_CANCEL;
#if MPEG_OPTION_DITHERING_ENABLED
case MPEG_OPTION_DITHERING:
result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0;
rb->set_option("Dithering", &result, INT, noyes, 2, NULL);
settings.displayoptions = (settings.displayoptions & ~LCD_YUV_DITHER)
| ((result != 0) ? LCD_YUV_DITHER : 0);
rb->lcd_yuv_set_options(settings.displayoptions);
break;
#endif /* MPEG_OPTION_DITHERING_ENABLED */
case MPEG_OPTION_DISPLAY_FPS:
rb->set_option("Display FPS",&settings.showfps,INT,
noyes, 2, NULL);
break;
case MPEG_OPTION_LIMIT_FPS:
rb->set_option("Limit FPS",&settings.limitfps,INT,
noyes, 2, NULL);
break;
case MPEG_OPTION_SKIP_FRAMES:
rb->set_option("Skip frames",&settings.skipframes,INT,
noyes, 2, NULL);
break;
default:
options_quit=1;
break;
}
} }
menu_exit(menu_id); return btn;
(void)menu;
} }
long mpeg_menu_sysevent(void)
{
return mpeg_menu_sysevent_id;
}
void mpeg_menu_sysevent_handle(void)
{
long id = mpeg_menu_sysevent();
if (id != 0)
rb->default_event_handler(id);
}
static void format_menu_item(struct menu_item *item, int bufsize,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
rb->vsnprintf(item->desc, bufsize, fmt, ap);
va_end(ap);
}
static bool mpeg_set_option(const char* string,
void* variable,
enum optiontype type,
const struct opt_items* options,
int numoptions,
void (*function)(int))
{
mpeg_menu_sysevent_clear();
/* This eats SYS_POWEROFF - :\ */
bool usb = rb->set_option(string, variable, type, options, numoptions,
function);
if (usb)
mpeg_menu_sysevent_id = ACTION_STD_CANCEL;
return usb;
}
#ifndef HAVE_LCD_COLOR #ifndef HAVE_LCD_COLOR
/* Cheapo splash implementation for the grey surface */ /* Cheapo splash implementation for the grey surface */
static void grey_splash(int ticks, const unsigned char *fmt, ...) static void grey_splash(int ticks, const unsigned char *fmt, ...)
@ -230,7 +230,7 @@ static void show_loading(struct vo_rect *rc)
lcd_(splash)(0, "Loading..."); lcd_(splash)(0, "Loading...");
} }
void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc) static void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc)
{ {
#define SLIDER_WIDTH (LCD_WIDTH-SLIDER_LMARGIN-SLIDER_RMARGIN) #define SLIDER_WIDTH (LCD_WIDTH-SLIDER_LMARGIN-SLIDER_RMARGIN)
#define SLIDER_X SLIDER_LMARGIN #define SLIDER_X SLIDER_LMARGIN
@ -291,7 +291,7 @@ void draw_slider(uint32_t range, uint32_t pos, struct vo_rect *rc)
} }
} }
bool display_thumb_image(const struct vo_rect *rc) static bool display_thumb_image(const struct vo_rect *rc)
{ {
if (!stream_display_thumb(rc)) if (!stream_display_thumb(rc))
{ {
@ -322,7 +322,7 @@ bool display_thumb_image(const struct vo_rect *rc)
} }
/* Add an amount to the specified time - with saturation */ /* Add an amount to the specified time - with saturation */
uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range) static uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range)
{ {
if (amount < 0) if (amount < 0)
{ {
@ -344,7 +344,7 @@ uint32_t increment_time(uint32_t val, int32_t amount, uint32_t range)
return val; return val;
} }
int get_start_time(uint32_t duration) static int get_start_time(uint32_t duration)
{ {
int button = 0; int button = 0;
int tmo = TIMEOUT_NOBLOCK; int tmo = TIMEOUT_NOBLOCK;
@ -420,73 +420,79 @@ int get_start_time(uint32_t duration)
rc_vid.r, rc_vid.b); rc_vid.r, rc_vid.b);
#ifndef HAVE_LCD_COLOR #ifndef HAVE_LCD_COLOR
/* Restore gray overlay dimensions */
stream_gray_show(true); stream_gray_show(true);
#endif #endif
while(slider_state < state9) while (slider_state < state9)
{ {
mpeg_menu_sysevent_clear();
button = tmo == TIMEOUT_BLOCK ? button = tmo == TIMEOUT_BLOCK ?
rb->button_get(true) : rb->button_get_w_tmo(tmo); rb->button_get(true) : rb->button_get_w_tmo(tmo);
button = mpeg_menu_sysevent_callback(button, -1);
switch (button) switch (button)
{ {
case BUTTON_NONE: case BUTTON_NONE:
break; break;
/* Coarse (1 minute) control */ /* Coarse (1 minute) control */
case MPEG_DOWN: case MPEG_START_TIME_DOWN:
case MPEG_DOWN | BUTTON_REPEAT: case MPEG_START_TIME_DOWN | BUTTON_REPEAT:
resume_time = increment_time(resume_time, -60*TS_SECOND, duration); resume_time = increment_time(resume_time, -60*TS_SECOND, duration);
slider_state = state0; slider_state = state0;
break; break;
case MPEG_UP: case MPEG_START_TIME_UP:
case MPEG_UP | BUTTON_REPEAT: case MPEG_START_TIME_UP | BUTTON_REPEAT:
resume_time = increment_time(resume_time, 60*TS_SECOND, duration); resume_time = increment_time(resume_time, 60*TS_SECOND, duration);
slider_state = state0; slider_state = state0;
break; break;
/* Fine (1 second) control */ /* Fine (1 second) control */
case MPEG_LEFT: case MPEG_START_TIME_LEFT:
case MPEG_LEFT | BUTTON_REPEAT: case MPEG_START_TIME_LEFT | BUTTON_REPEAT:
#ifdef MPEG_SCROLL_UP #ifdef MPEG_START_TIME_SCROLL_UP
case MPEG_SCROLL_UP: case MPEG_START_TIME_SCROLL_UP:
case MPEG_SCROLL_UP | BUTTON_REPEAT: case MPEG_START_TIME_SCROLL_UP | BUTTON_REPEAT:
#endif #endif
resume_time = increment_time(resume_time, -TS_SECOND, duration); resume_time = increment_time(resume_time, -TS_SECOND, duration);
slider_state = state0; slider_state = state0;
break; break;
case MPEG_RIGHT: case MPEG_START_TIME_RIGHT:
case MPEG_RIGHT | BUTTON_REPEAT: case MPEG_START_TIME_RIGHT | BUTTON_REPEAT:
#ifdef MPEG_SCROLL_DOWN #ifdef MPEG_START_TIME_SCROLL_DOWN
case MPEG_SCROLL_DOWN: case MPEG_START_TIME_SCROLL_DOWN:
case MPEG_SCROLL_DOWN | BUTTON_REPEAT: case MPEG_START_TIME_SCROLL_DOWN | BUTTON_REPEAT:
#endif #endif
resume_time = increment_time(resume_time, TS_SECOND, duration); resume_time = increment_time(resume_time, TS_SECOND, duration);
slider_state = state0; slider_state = state0;
break; break;
case MPEG_SELECT: case MPEG_START_TIME_SELECT:
settings.resume_time = resume_time; settings.resume_time = resume_time;
case MPEG_EXIT: button = MPEG_START_SEEK;
slider_state = state9; slider_state = state9;
break; break;
case SYS_USB_CONNECTED: case MPEG_START_TIME_EXIT:
button = MPEG_START_EXIT;
slider_state = state9; slider_state = state9;
#ifndef HAVE_LCD_COLOR break;
stream_gray_show(false);
#endif case ACTION_STD_CANCEL:
cancel_cpu_boost(); button = MPEG_START_QUIT;
slider_state = state9;
break;
default: default:
rb->default_event_handler(button); rb->default_event_handler(button);
rb->yield(); rb->yield();
continue; continue;
} }
switch(slider_state) switch (slider_state)
{ {
case state0: case state0:
trigger_cpu_boost(); trigger_cpu_boost();
@ -500,12 +506,13 @@ int get_start_time(uint32_t duration)
display_thumb_image(&rc_vid); display_thumb_image(&rc_vid);
slider_state = state2; slider_state = state2;
case state2: case state2:
case state9:
cancel_cpu_boost(); cancel_cpu_boost();
tmo = TIMEOUT_BLOCK; tmo = TIMEOUT_BLOCK;
default: default:
break; break;
} }
rb->yield();
} }
#ifndef HAVE_LCD_COLOR #ifndef HAVE_LCD_COLOR
@ -519,46 +526,17 @@ int get_start_time(uint32_t duration)
return button; return button;
} }
enum mpeg_start_id mpeg_start_menu(uint32_t duration) static int show_start_menu(uint32_t duration)
{ {
int menu_id; int menu_id;
int result = 0; int result = 0;
int menu_quit = 0; bool menu_quit = false;
/* add the resume time to the menu display */ /* add the resume time to the menu display */
char resume_str[32]; char resume_str[32];
char hms_str[32]; char hms_str[32];
struct hms hms; struct hms hms;
ts_to_hms(settings.resume_time, &hms);
hms_format(hms_str, sizeof(hms_str), &hms);
if (settings.enable_start_menu == 0)
{
rb->snprintf(resume_str, sizeof(resume_str), "Yes: %s", hms_str);
struct opt_items resume_no_yes[2] =
{
{ "No", -1 },
{ resume_str, -1 },
};
if (settings.resume_time == 0)
return MPEG_START_RESTART;
rb->set_option("Resume", &result, INT,
resume_no_yes, 2, NULL);
if (result == 0)
{
settings.resume_time = 0;
return MPEG_START_RESTART;
}
else
return MPEG_START_RESUME;
}
rb->snprintf(resume_str, sizeof(resume_str), "Resume at: %s", hms_str);
struct menu_item items[] = struct menu_item items[] =
{ {
[MPEG_START_RESTART] = [MPEG_START_RESTART] =
@ -567,50 +545,65 @@ enum mpeg_start_id mpeg_start_menu(uint32_t duration)
{ resume_str, NULL }, { resume_str, NULL },
[MPEG_START_SEEK] = [MPEG_START_SEEK] =
{ "Set start time", NULL }, { "Set start time", NULL },
[MPEG_START_SETTINGS] =
{ "Settings", NULL },
[MPEG_START_QUIT] = [MPEG_START_QUIT] =
{ "Quit mpegplayer", NULL }, { "Quit mpegplayer", NULL },
}; };
ts_to_hms(settings.resume_time, &hms);
hms_format(hms_str, sizeof(hms_str), &hms);
format_menu_item(&items[MPEG_START_RESUME], sizeof (resume_str),
"Resume at: %s", hms_str);
menu_id = menu_init(rb, items, sizeof(items) / sizeof(*items), menu_id = menu_init(rb, items, ARRAYLEN(items),
NULL, NULL, NULL, NULL); mpeg_menu_sysevent_callback, NULL, NULL, NULL);
rb->button_clear_queue(); rb->button_clear_queue();
while(menu_quit == 0) while (!menu_quit)
{ {
mpeg_menu_sysevent_clear();
result = menu_show(menu_id); result = menu_show(menu_id);
switch (result) switch (result)
{ {
case MPEG_START_RESTART: case MPEG_START_RESTART:
settings.resume_time = 0; settings.resume_time = 0;
menu_quit = 1; menu_quit = true;
break; break;
case MPEG_START_RESUME:
menu_quit = 1;
break;
case MPEG_START_SEEK:
{
if (!stream_can_seek())
{
rb->splash(HZ, "Unavailable");
break;
}
bool vis = stream_show_vo(false); case MPEG_START_RESUME:
if (get_start_time(duration) == MPEG_SELECT) menu_quit = true;
menu_quit = 1; break;
stream_show_vo(vis);
case MPEG_START_SEEK:
if (!stream_can_seek())
{
rb->splash(HZ, "Unavailable");
break; break;
} }
case MPEG_START_QUIT:
menu_quit = 1; result = get_start_time(duration);
break;
default: if (result != MPEG_START_EXIT)
result = MPEG_START_QUIT; menu_quit = true;
menu_quit = 1; break;
case MPEG_START_SETTINGS:
if (mpeg_menu(MPEG_MENU_HIDE_QUIT_ITEM) != MPEG_MENU_QUIT)
break; break;
/* Fall-through */
default:
result = MPEG_START_QUIT;
menu_quit = true;
break;
}
if (mpeg_menu_sysevent() != 0)
{
result = MPEG_START_QUIT;
menu_quit = true;
} }
} }
@ -622,7 +615,116 @@ enum mpeg_start_id mpeg_start_menu(uint32_t duration)
return result; return result;
} }
void clear_resume_count(void) /* Return the desired resume action */
int mpeg_start_menu(uint32_t duration)
{
mpeg_menu_sysevent_clear();
switch (settings.resume_options)
{
case MPEG_RESUME_MENU_IF_INCOMPLETE:
if (!stream_can_seek() || settings.resume_time == 0)
{
case MPEG_RESUME_RESTART:
settings.resume_time = 0;
return MPEG_START_RESTART;
}
default:
case MPEG_RESUME_MENU_ALWAYS:
return show_start_menu(duration);
case MPEG_RESUME_ALWAYS:
return MPEG_START_SEEK;
}
}
/** MPEG Menu **/
static void display_options(void)
{
int result;
int menu_id;
bool menu_quit = false;
static const struct menu_item items[] = {
#if MPEG_OPTION_DITHERING_ENABLED
[MPEG_OPTION_DITHERING] =
{ "Dithering", NULL },
#endif
[MPEG_OPTION_DISPLAY_FPS] =
{ "Display FPS", NULL },
[MPEG_OPTION_LIMIT_FPS] =
{ "Limit FPS", NULL },
[MPEG_OPTION_SKIP_FRAMES] =
{ "Skip frames", NULL },
};
menu_id = menu_init(rb, items, ARRAYLEN(items),
mpeg_menu_sysevent_callback, NULL, NULL, NULL);
rb->button_clear_queue();
while (!menu_quit)
{
mpeg_menu_sysevent_clear();
result = menu_show(menu_id);
switch (result)
{
#if MPEG_OPTION_DITHERING_ENABLED
case MPEG_OPTION_DITHERING:
result = (settings.displayoptions & LCD_YUV_DITHER) ? 1 : 0;
mpeg_set_option("Dithering", &result, INT, noyes, 2, NULL);
settings.displayoptions =
(settings.displayoptions & ~LCD_YUV_DITHER)
| ((result != 0) ? LCD_YUV_DITHER : 0);
rb->lcd_yuv_set_options(settings.displayoptions);
break;
#endif /* MPEG_OPTION_DITHERING_ENABLED */
case MPEG_OPTION_DISPLAY_FPS:
mpeg_set_option("Display FPS", &settings.showfps, INT,
noyes, 2, NULL);
break;
case MPEG_OPTION_LIMIT_FPS:
mpeg_set_option("Limit FPS", &settings.limitfps, INT,
noyes, 2, NULL);
break;
case MPEG_OPTION_SKIP_FRAMES:
mpeg_set_option("Skip frames", &settings.skipframes, INT,
noyes, 2, NULL);
break;
default:
menu_quit = true;
break;
}
if (mpeg_menu_sysevent() != 0)
menu_quit = true;
}
menu_exit(menu_id);
}
static void resume_options(void)
{
static const struct opt_items items[MPEG_RESUME_NUM_OPTIONS] = {
[MPEG_RESUME_MENU_ALWAYS] =
{ "Start menu", -1 },
[MPEG_RESUME_MENU_IF_INCOMPLETE] =
{ "Start menu if not completed", -1 },
[MPEG_RESUME_ALWAYS] =
{ "Resume automatically", -1 },
[MPEG_RESUME_RESTART] =
{ "Play from beginning", -1 },
};
mpeg_set_option("Resume Options", &settings.resume_options,
INT, items, MPEG_RESUME_NUM_OPTIONS, NULL);
}
static void clear_resume_count(void)
{ {
configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config), configfile_save(SETTINGS_FILENAME, config, ARRAYLEN(config),
SETTINGS_VERSION); SETTINGS_VERSION);
@ -633,58 +735,69 @@ void clear_resume_count(void)
configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0); configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
} }
enum mpeg_menu_id mpeg_menu(void) int mpeg_menu(unsigned flags)
{ {
int menu_id; int menu_id;
int result; int result;
int menu_quit=0; bool menu_quit = false;
int item_count;
/* add the clear resume option to the menu display */
char clear_str[32]; char clear_str[32];
rb->snprintf(clear_str, sizeof(clear_str),
"Clear all resumes: %u", settings.resume_count);
struct menu_item items[] = { struct menu_item items[] = {
[MPEG_MENU_DISPLAY_SETTINGS] = [MPEG_MENU_DISPLAY_SETTINGS] =
{ "Display Options", NULL }, { "Display Options", NULL },
[MPEG_MENU_ENABLE_START_MENU] = [MPEG_MENU_ENABLE_START_MENU] =
{ "Start menu", NULL }, { "Resume Options", NULL },
[MPEG_MENU_CLEAR_RESUMES] = [MPEG_MENU_CLEAR_RESUMES] =
{ clear_str, NULL }, { clear_str, NULL },
[MPEG_MENU_QUIT] = [MPEG_MENU_QUIT] =
{ "Quit mpegplayer", NULL }, { "Quit mpegplayer", NULL },
}; };
menu_id = menu_init(rb, items, ARRAYLEN(items), item_count = ARRAYLEN(items);
NULL, NULL, NULL, NULL);
if (flags & MPEG_MENU_HIDE_QUIT_ITEM)
item_count--;
menu_id = menu_init(rb, items, item_count,
mpeg_menu_sysevent_callback, NULL, NULL, NULL);
rb->button_clear_queue(); rb->button_clear_queue();
while (menu_quit == 0) while (!menu_quit)
{ {
result=menu_show(menu_id); mpeg_menu_sysevent_clear();
switch(result) /* Format and add resume option to the menu display */
format_menu_item(&items[MPEG_MENU_CLEAR_RESUMES], sizeof(clear_str),
"Clear all resumes: %u", settings.resume_count);
result = menu_show(menu_id);
switch (result)
{ {
case MPEG_MENU_DISPLAY_SETTINGS: case MPEG_MENU_DISPLAY_SETTINGS:
display_options(); display_options();
break; break;
case MPEG_MENU_ENABLE_START_MENU:
rb->set_option("Start menu", case MPEG_MENU_ENABLE_START_MENU:
&settings.enable_start_menu, resume_options();
INT, enabledisable, 2, NULL); break;
break;
case MPEG_MENU_CLEAR_RESUMES: case MPEG_MENU_CLEAR_RESUMES:
clear_resume_count(); clear_resume_count();
rb->snprintf(clear_str, sizeof(clear_str), break;
"Clear all resumes: %u", 0);
break; case MPEG_MENU_QUIT:
case MPEG_MENU_QUIT: default:
default: menu_quit = true;
menu_quit=1; break;
if (result == MENU_ATTACHED_USB) }
result = MPEG_MENU_QUIT;
break; if (mpeg_menu_sysevent() != 0)
{
result = MPEG_MENU_QUIT;
menu_quit = true;
} }
} }
@ -702,7 +815,7 @@ void init_settings(const char* filename)
settings.showfps = 0; /* Do not show FPS */ settings.showfps = 0; /* Do not show FPS */
settings.limitfps = 1; /* Limit FPS */ settings.limitfps = 1; /* Limit FPS */
settings.skipframes = 1; /* Skip frames */ settings.skipframes = 1; /* Skip frames */
settings.enable_start_menu = 1; /* Enable start menu */ settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */
settings.resume_count = -1; settings.resume_count = -1;
#if MPEG_OPTION_DITHERING_ENABLED #if MPEG_OPTION_DITHERING_ENABLED
settings.displayoptions = 0; /* No visual effects */ settings.displayoptions = 0; /* No visual effects */
@ -754,8 +867,8 @@ void save_settings(void)
settings.limitfps); settings.limitfps);
configfile_update_entry(SETTINGS_FILENAME, "Skip frames", configfile_update_entry(SETTINGS_FILENAME, "Skip frames",
settings.skipframes); settings.skipframes);
configfile_update_entry(SETTINGS_FILENAME, "Enable start menu", configfile_update_entry(SETTINGS_FILENAME, "Resume options",
settings.enable_start_menu); settings.resume_options);
/* If this was a new resume entry then update the total resume count */ /* If this was a new resume entry then update the total resume count */
if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename, if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename,

View file

@ -1,6 +1,10 @@
#include "plugin.h" #include "plugin.h"
#define SETTINGS_VERSION 3
#define SETTINGS_MIN_VERSION 1
#define SETTINGS_FILENAME "mpegplayer.cfg"
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200)
#define MPEG_OPTION_DITHERING_ENABLED 1 #define MPEG_OPTION_DITHERING_ENABLED 1
#endif #endif
@ -19,12 +23,23 @@ enum mpeg_option_id
MPEG_OPTION_SKIP_FRAMES, MPEG_OPTION_SKIP_FRAMES,
}; };
enum mpeg_resume_id
{
MPEG_RESUME_MENU_ALWAYS = 0,
MPEG_RESUME_MENU_IF_INCOMPLETE,
MPEG_RESUME_RESTART,
MPEG_RESUME_ALWAYS,
MPEG_RESUME_NUM_OPTIONS,
};
enum mpeg_start_id enum mpeg_start_id
{ {
MPEG_START_RESTART, MPEG_START_RESTART,
MPEG_START_RESUME, MPEG_START_RESUME,
MPEG_START_SEEK, MPEG_START_SEEK,
MPEG_START_SETTINGS,
MPEG_START_QUIT, MPEG_START_QUIT,
MPEG_START_EXIT,
}; };
enum mpeg_menu_id enum mpeg_menu_id
@ -39,7 +54,7 @@ struct mpeg_settings {
int showfps; /* flag to display fps */ int showfps; /* flag to display fps */
int limitfps; /* flag to limit fps */ int limitfps; /* flag to limit fps */
int skipframes; /* flag to skip frames */ int skipframes; /* flag to skip frames */
int enable_start_menu; /* flag to enable/disable start menu */ int resume_options; /* type of resume action at start */
int resume_count; /* total # of resumes in config file */ int resume_count; /* total # of resumes in config file */
int resume_time; /* resume time for current mpeg (in half minutes) */ int resume_time; /* resume time for current mpeg (in half minutes) */
char resume_filename[MAX_PATH]; /* filename of current mpeg */ char resume_filename[MAX_PATH]; /* filename of current mpeg */
@ -50,9 +65,18 @@ struct mpeg_settings {
extern struct mpeg_settings settings; extern struct mpeg_settings settings;
int get_start_time(uint32_t duration); int mpeg_start_menu(uint32_t duration);
enum mpeg_start_id mpeg_start_menu(uint32_t duration);
enum mpeg_menu_id mpeg_menu(void); enum
{
MPEG_MENU_HIDE_QUIT_ITEM = 0x1, /* Don't show the quit item */
};
int mpeg_menu(unsigned flags);
void mpeg_menu_sysevent_clear(void);
long mpeg_menu_sysevent(void);
int mpeg_menu_sysevent_callback(int btn, int menu);
void mpeg_menu_sysevent_handle(void);
void init_settings(const char* filename); void init_settings(const char* filename);
void save_settings(void); void save_settings(void);
void clear_resume_count(void);

View file

@ -822,6 +822,11 @@ static void wvs_refresh(int hint)
if (hint == WVS_REFRESH_DEFAULT) { if (hint == WVS_REFRESH_DEFAULT) {
/* The default which forces no updates */ /* The default which forces no updates */
/* Make sure Rockbox doesn't turn off the player because of
too little activity */
if (wvs.status == WVS_STATUS_PLAYING)
rb->reset_poweroff_timer();
/* Redraw the current or possibly extract a new video frame */ /* Redraw the current or possibly extract a new video frame */
if ((wvs.auto_refresh & WVS_REFRESH_VIDEO) && if ((wvs.auto_refresh & WVS_REFRESH_VIDEO) &&
TIME_AFTER(tick, wvs.print_tick)) { TIME_AFTER(tick, wvs.print_tick)) {
@ -942,8 +947,6 @@ static void wvs_show(unsigned show)
/* Uncover clipped video area and redraw it */ /* Uncover clipped video area and redraw it */
wvs.flags &= ~WVS_SHOW; wvs.flags &= ~WVS_SHOW;
stream_vo_set_clip(NULL);
draw_clear_area(0, 0, wvs.width, wvs.height); draw_clear_area(0, 0, wvs.width, wvs.height);
if (!(show & WVS_NODRAW)) { if (!(show & WVS_NODRAW)) {
@ -951,7 +954,10 @@ static void wvs_show(unsigned show)
draw_update_rect(0, 0, wvs.width, wvs.height); draw_update_rect(0, 0, wvs.width, wvs.height);
vo_unlock(); vo_unlock();
stream_vo_set_clip(NULL);
stream_draw_frame(false); stream_draw_frame(false);
} else {
stream_vo_set_clip(NULL);
} }
} }
} }
@ -1180,14 +1186,20 @@ static void wvs_resume(void)
stream_resume(); stream_resume();
} }
/* Stop playback - remember the resume point if not already stopped */ /* Stop playback - remember the resume point if not closed */
static void wvs_stop(void) static void wvs_stop(void)
{ {
uint32_t resume_time;
wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME); wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME);
wvs_show(WVS_HIDE | WVS_NODRAW); wvs_show(WVS_HIDE | WVS_NODRAW);
if (stream_stop() != STREAM_STOPPED) stream_stop();
settings.resume_time = stream_get_resume_time();
resume_time = stream_get_resume_time();
if (resume_time != INVALID_TIMESTAMP)
settings.resume_time = resume_time;
} }
/* Perform a seek if seeking is possible for this stream - if playing, a delay /* Perform a seek if seeking is possible for this stream - if playing, a delay
@ -1242,11 +1254,12 @@ static void button_loop(void)
/* Gently poll the video player for EOS and handle UI */ /* Gently poll the video player for EOS and handle UI */
while (stream_status() != STREAM_STOPPED) while (stream_status() != STREAM_STOPPED)
{ {
int button = rb->button_get_w_tmo(WVS_MIN_UPDATE_INTERVAL); int button;
/* Make sure Rockbox doesn't turn off the player because of mpeg_menu_sysevent_clear();
too little activity */ button = rb->button_get_w_tmo(WVS_MIN_UPDATE_INTERVAL);
rb->reset_poweroff_timer();
button = mpeg_menu_sysevent_callback(button, -1);
switch (button) switch (button)
{ {
@ -1288,7 +1301,7 @@ static void button_loop(void)
stream_show_vo(false); stream_show_vo(false);
backlight_use_settings(rb); backlight_use_settings(rb);
result = mpeg_menu(); result = mpeg_menu(0);
/* The menu can change the font, so restore */ /* The menu can change the font, so restore */
rb->lcd_setfont(FONT_SYSFIXED); rb->lcd_setfont(FONT_SYSFIXED);
@ -1298,6 +1311,7 @@ static void button_loop(void)
case MPEG_MENU_QUIT: case MPEG_MENU_QUIT:
wvs_stop(); wvs_stop();
break; break;
default: default:
/* If not stopped, show video again */ /* If not stopped, show video again */
if (state != STREAM_STOPPED) { if (state != STREAM_STOPPED) {
@ -1316,6 +1330,7 @@ static void button_loop(void)
} /* MPEG_MENU: */ } /* MPEG_MENU: */
case MPEG_STOP: case MPEG_STOP:
case ACTION_STD_CANCEL:
{ {
wvs_stop(); wvs_stop();
break; break;
@ -1349,16 +1364,11 @@ static void button_loop(void)
break; break;
} /* MPEG_RW: MPEG_FF: */ } /* MPEG_RW: MPEG_FF: */
case SYS_POWEROFF:
case SYS_USB_CONNECTED:
/* Stop and get the resume time before closing the file early */
wvs_stop();
stream_close();
save_settings(); /* Save settings (if they have changed) */
/* Fall-through */
default: default:
{
rb->default_event_handler(button); rb->default_event_handler(button);
break; break;
} /* default: */
} }
rb->yield(); rb->yield();
@ -1428,6 +1438,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
save_settings(); /* Save settings (if they have changed) */ save_settings(); /* Save settings (if they have changed) */
status = PLUGIN_OK; status = PLUGIN_OK;
mpeg_menu_sysevent_handle();
} else { } else {
DEBUGF("Could not open %s\n", (char*)parameter); DEBUGF("Could not open %s\n", (char*)parameter);
switch (err) switch (err)

View file

@ -133,7 +133,7 @@ void str_data_notify_received(struct stream *str)
static void stream_mgr_init_state(void) static void stream_mgr_init_state(void)
{ {
stream_mgr.filename = NULL; stream_mgr.filename = NULL;
stream_mgr.resume_time = 0; stream_mgr.resume_time = INVALID_TIMESTAMP;
stream_mgr.seeked = false; stream_mgr.seeked = false;
} }
@ -341,6 +341,26 @@ static uint32_t stream_seek_intl(uint32_t time, int whence,
return parser_seek_time(time); return parser_seek_time(time);
} }
/* Store the resume time at the last seek/current clock point */
static void stream_remember_resume_time(void)
{
/* Assume invalidity */
stream_mgr.resume_time = 0;
if (stream_can_seek())
{
/* Read the current stream time or the last seeked position */
uint32_t start;
uint32_t time = stream_get_seek_time(&start);
if (time >= str_parser.start_pts && time < str_parser.end_pts)
{
/* Save the current stream time */
stream_mgr.resume_time = time - start;
}
}
}
/* Handle STREAM_OPEN */ /* Handle STREAM_OPEN */
void stream_on_open(const char *filename) void stream_on_open(const char *filename)
{ {
@ -396,11 +416,11 @@ static void stream_on_play(void)
/* Seek to initial position and set clock to that time */ /* Seek to initial position and set clock to that time */
/* Save the resume time */ /* Save the resume time */
start = str_parser.last_seek_time - str_parser.start_pts; stream_remember_resume_time();
stream_mgr.resume_time = start;
/* Prepare seek to start point */ /* Prepare seek to start point */
start = stream_seek_intl(start, SEEK_SET, STREAM_STOPPED, NULL); start = stream_seek_intl(stream_mgr.resume_time, SEEK_SET,
STREAM_STOPPED, NULL);
/* Sync and start - force buffer fill */ /* Sync and start - force buffer fill */
stream_start_playback(start, true); stream_start_playback(start, true);
@ -485,21 +505,8 @@ static void stream_on_stop(bool reply)
/* Pause the clock */ /* Pause the clock */
pcm_output_play_pause(false); pcm_output_play_pause(false);
/* Assume invalidity */ /* Update the resume time info */
stream_mgr.resume_time = 0; stream_remember_resume_time();
if (stream_can_seek())
{
/* Read the current stream time or the last seeked position */
uint32_t start;
uint32_t time = stream_get_seek_time(&start);
if (time >= str_parser.start_pts && time < str_parser.end_pts)
{
/* Save the current stream time */
stream_mgr.resume_time = time - start;
}
}
/* Not stopped = paused or playing */ /* Not stopped = paused or playing */
stream_mgr.seeked = false; stream_mgr.seeked = false;
@ -555,6 +562,7 @@ static void stream_on_seek(struct stream_seek_data *skd)
} }
time = stream_seek_intl(time, whence, stream_mgr.status, &buffer); time = stream_seek_intl(time, whence, stream_mgr.status, &buffer);
stream_remember_resume_time();
if (stream_mgr.status == STREAM_PLAYING) if (stream_mgr.status == STREAM_PLAYING)
{ {