1
0
Fork 0
forked from len0rd/rockbox

FS#7487 - mpegplayer - video start time seek with resume

by John S. Gwynne & Brian J. Morey
This should stop the patch from breaking again and give them opportunity to improve it further.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15052 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Robert Kukla 2007-10-09 20:42:20 +00:00
parent ce135909b9
commit fd3fe45bc1
17 changed files with 1241 additions and 219 deletions

View file

@ -518,6 +518,8 @@ static const struct plugin_api rockbox_api = {
talk_disable_menus, talk_disable_menus,
talk_enable_menus, talk_enable_menus,
button_available,
}; };
int plugin_load(const char* plugin, void* parameter) int plugin_load(const char* plugin, void* parameter)

View file

@ -112,7 +112,7 @@
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 79 #define PLUGIN_API_VERSION 80
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
@ -635,6 +635,8 @@ struct plugin_api {
void (*talk_disable_menus)(void); void (*talk_disable_menus)(void);
void (*talk_enable_menus)(void); void (*talk_enable_menus)(void);
int (*button_available)(void);
}; };
/* plugin header */ /* plugin header */

View file

@ -55,12 +55,14 @@ int configfile_save(const char *filename, struct configdata *cfg,
if(fd < 0) if(fd < 0)
return fd*10 - 1; return fd*10 - 1;
cfg_rb->fdprintf(fd, "file version: %d\n", version); /* pre-allocate 10 bytes for INT */
cfg_rb->fdprintf(fd, "file version: %10d\n", version);
for(i = 0;i < num_items;i++) { for(i = 0;i < num_items;i++) {
switch(cfg[i].type) { switch(cfg[i].type) {
case TYPE_INT: case TYPE_INT:
cfg_rb->fdprintf(fd, "%s: %d\n", /* pre-allocate 10 bytes for INT */
cfg_rb->fdprintf(fd, "%s: %10d\n",
cfg[i].name, cfg[i].name,
*cfg[i].val); *cfg[i].val);
break; break;
@ -141,3 +143,72 @@ int configfile_load(const char *filename, struct configdata *cfg,
cfg_rb->close(fd); cfg_rb->close(fd);
return 0; return 0;
} }
int configfile_get_value(const char* filename, const char* name)
{
int fd;
char *pname;
char *pval;
char buf[MAX_PATH];
get_cfg_filename(buf, MAX_PATH, filename);
fd = cfg_rb->open(buf, O_RDONLY);
if(fd < 0)
return -1;
while(cfg_rb->read_line(fd, buf, MAX_PATH) > 0)
{
cfg_rb->settings_parseline(buf, &pname, &pval);
if(!cfg_rb->strcmp(name, pname))
{
cfg_rb->close(fd);
return cfg_rb->atoi(pval);
}
}
cfg_rb->close(fd);
return -1;
}
int configfile_update_entry(const char* filename, const char* name, int val)
{
int fd;
char *pname;
char *pval;
char path[MAX_PATH];
char buf[256];
int found = 0;
int line_len = 0;
int pos = 0;
/* open the current config file */
get_cfg_filename(path, MAX_PATH, filename);
fd = cfg_rb->open(path, O_RDWR);
if(fd < 0)
return -1;
/* read in the current stored settings */
while((line_len = cfg_rb->read_line(fd, buf, 256)) > 0)
{
cfg_rb->settings_parseline(buf, &pname, &pval);
if(!cfg_rb->strcmp(name, pname))
{
found = 1;
cfg_rb->lseek(fd, pos, SEEK_SET);
/* pre-allocate 10 bytes for INT */
cfg_rb->fdprintf(fd, "%s: %10d\n", pname, val);
break;
}
pos += line_len;
}
/* if (name/val) is a new entry just append to file */
if (found == 0)
/* pre-allocate 10 bytes for INT */
cfg_rb->fdprintf(fd, "%s: %10d\n", name, val);
cfg_rb->close(fd);
return found;
}

View file

@ -38,9 +38,41 @@ struct configdata
}; };
void configfile_init(struct plugin_api* newrb); void configfile_init(struct plugin_api* newrb);
/* configfile_save - Given configdata entries this function will
create a config file with these entries, destroying any
previous config file of the same name */
int configfile_save(const char *filename, struct configdata *cfg, int configfile_save(const char *filename, struct configdata *cfg,
int num_items, int version); int num_items, int version);
int configfile_load(const char *filename, struct configdata *cfg, int configfile_load(const char *filename, struct configdata *cfg,
int num_items, int min_version); int num_items, int min_version);
/* configfile_get_value - Given a key name, this function will
return the integer value for that key.
Input:
filename = config file filename
name = (name/value) pair name entry
Return:
value if (name/value) pair is found
-1 if entry is not found
*/
int configfile_get_value(const char* filename, const char* name);
/* configure_update_entry - Given a key name and integer value
this function will update the entry if found, or add it if
not found.
Input:
filename = config file filename
name = (name/value) pair name entry
val = new value for (name/value) pair
Return:
1 if the (name/value) pair was found and updated with the new value
0 if the (name/value) pair was added as a new entry
-1 if error
*/
int configfile_update_entry(const char* filename, const char* name, int val);
#endif #endif

View file

@ -54,6 +54,8 @@ static void * mpeg_malloc_internal (unsigned char *mallocbuf,
x = &mallocbuf[*mem_ptr]; x = &mallocbuf[*mem_ptr];
*mem_ptr += (size + 3) & ~3; /* Keep memory 32-bit aligned */ *mem_ptr += (size + 3) & ~3; /* Keep memory 32-bit aligned */
rb->memset(x,0,size);
return x; return x;
(void)reason; (void)reason;
} }
@ -116,7 +118,7 @@ void * mpeg2_malloc(unsigned size, mpeg2_alloc_t reason)
void mpeg2_free(void *ptr) void mpeg2_free(void *ptr)
{ {
(void)ptr; mpeg2_mem_ptr = (void *)ptr - (void *)mpeg2_mallocbuf;
} }
/* The following are expected by libmad */ /* The following are expected by libmad */
@ -141,7 +143,7 @@ void * codec_calloc(size_t nmemb, size_t size)
void codec_free(void* ptr) void codec_free(void* ptr)
{ {
(void)ptr; mem_ptr = (void *)ptr - (void *)mallocbuf;
} }
void *memmove(void *dest, const void *src, size_t n) void *memmove(void *dest, const void *src, size_t n)

View file

@ -58,7 +58,7 @@ static const uint8_t default_intra_quantizer_matrix[64] ICONST_ATTR = {
83 83
}; };
uint8_t mpeg2_scan_norm[64] IDATA_ATTR = { uint8_t default_mpeg2_scan_norm[64] IDATA_ATTR = {
/* Zig-Zag scan pattern */ /* Zig-Zag scan pattern */
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
@ -66,7 +66,7 @@ uint8_t mpeg2_scan_norm[64] IDATA_ATTR = {
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
}; };
uint8_t mpeg2_scan_alt[64] IDATA_ATTR = { uint8_t default_mpeg2_scan_alt[64] IDATA_ATTR = {
/* Alternate scan pattern */ /* Alternate scan pattern */
0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49, 0, 8, 16, 24, 1, 9, 2, 10, 17, 25, 32, 40, 48, 56, 57, 49,
41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43, 41, 33, 26, 18, 3, 11, 4, 12, 19, 27, 34, 42, 50, 58, 35, 43,
@ -74,6 +74,9 @@ uint8_t mpeg2_scan_alt[64] IDATA_ATTR = {
53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63 53, 61, 22, 30, 7, 15, 23, 31, 38, 46, 54, 62, 39, 47, 55, 63
}; };
uint8_t mpeg2_scan_norm[64] IDATA_ATTR;
uint8_t mpeg2_scan_alt[64] IDATA_ATTR;
void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec) void mpeg2_header_state_init (mpeg2dec_t * mpeg2dec)
{ {
if (mpeg2dec->sequence.width != (unsigned)-1) { if (mpeg2dec->sequence.width != (unsigned)-1) {

View file

@ -260,6 +260,8 @@ static void mpeg2_idct_add_c (const int last, int16_t * block,
void mpeg2_idct_init (void) void mpeg2_idct_init (void)
{ {
extern uint8_t default_mpeg2_scan_norm[64];
extern uint8_t default_mpeg2_scan_alt[64];
extern uint8_t mpeg2_scan_norm[64]; extern uint8_t mpeg2_scan_norm[64];
extern uint8_t mpeg2_scan_alt[64]; extern uint8_t mpeg2_scan_alt[64];
int i, j; int i, j;
@ -274,10 +276,10 @@ void mpeg2_idct_init (void)
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
{ {
j = mpeg2_scan_norm[i]; j = default_mpeg2_scan_norm[i];
mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
j = mpeg2_scan_alt[i]; j = default_mpeg2_scan_alt[i];
mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
} }
} }

View file

@ -509,6 +509,8 @@ static void mpeg2_idct_add_c (int last, int16_t * block,
void mpeg2_idct_init (void) void mpeg2_idct_init (void)
{ {
extern uint8_t default_mpeg2_scan_norm[64];
extern uint8_t default_mpeg2_scan_alt[64];
extern uint8_t mpeg2_scan_norm[64]; extern uint8_t mpeg2_scan_norm[64];
extern uint8_t mpeg2_scan_alt[64]; extern uint8_t mpeg2_scan_alt[64];
int i, j; int i, j;
@ -518,10 +520,10 @@ void mpeg2_idct_init (void)
for (i = 0; i < 64; i++) for (i = 0; i < 64; i++)
{ {
j = mpeg2_scan_norm[i]; j = default_mpeg2_scan_norm[i];
mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); mpeg2_scan_norm[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
j = mpeg2_scan_alt[i]; j = default_mpeg2_scan_alt[i];
mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2); mpeg2_scan_alt[i] = ((j & 0x36) >> 1) | ((j & 0x09) << 2);
} }
} }

View file

@ -7,20 +7,99 @@
extern struct plugin_api* rb; extern struct plugin_api* rb;
struct mpeg_settings settings; struct mpeg_settings settings;
static struct mpeg_settings old_settings;
ssize_t seek_PTS(int in_file, int startTime, int accept_button);
void display_thumb(int in_file);
#ifndef HAVE_LCD_COLOR
void gray_show(bool enable);
#endif
#define SETTINGS_VERSION 2 #define SETTINGS_VERSION 2
#define SETTINGS_MIN_VERSION 1 #define SETTINGS_MIN_VERSION 1
#define SETTINGS_FILENAME "mpegplayer.cfg" #define SETTINGS_FILENAME "mpegplayer.cfg"
enum slider_state_t {state0, state1, state2,
state3, state4, state5} slider_state;
volatile long thumbDelayTimer;
/* button definitions */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
(CONFIG_KEYPAD == IRIVER_H300_PAD)
#define MPEG_SELECT BUTTON_ON
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_SCROLL_DOWN BUTTON_UP
#define MPEG_SCROLL_UP BUTTON_DOWN
#define MPEG_EXIT BUTTON_OFF
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
#define MPEG_SELECT BUTTON_PLAY
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_SCROLL_DOWN BUTTON_UP
#define MPEG_SCROLL_UP BUTTON_DOWN
#define MPEG_EXIT BUTTON_POWER
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
#define MPEG_SELECT BUTTON_SELECT
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_SCROLL_DOWN BUTTON_SCROLL_FWD
#define MPEG_SCROLL_UP BUTTON_SCROLL_BACK
#define MPEG_EXIT BUTTON_MENU
#elif CONFIG_KEYPAD == GIGABEAT_PAD
#define MPEG_SELECT BUTTON_SELECT
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN
#define MPEG_SCROLL_DOWN BUTTON_VOL_DOWN
#define MPEG_SCROLL_UP BUTTON_VOL_UP
#define MPEG_EXIT BUTTON_POWER
#elif CONFIG_KEYPAD == IRIVER_H10_PAD
#define MPEG_SELECT BUTTON_PLAY
#define MPEG_SCROLL_UP BUTTON_SCROLL_UP
#define MPEG_SCROLL_DOWN BUTTON_SCROLL_DOWN
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_EXIT BUTTON_POWER
#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
#define MPEG_SELECT BUTTON_SELECT
#define MPEG_SCROLL_UP BUTTON_SCROLL_UP
#define MPEG_SCROLL_DOWN BUTTON_SCROLL_DOWN
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN
#define MPEG_EXIT BUTTON_POWER
#elif (CONFIG_KEYPAD == SANSA_C200_PAD)
#define MPEG_SELECT BUTTON_SELECT
#define MPEG_SCROLL_UP BUTTON_VOL_UP
#define MPEG_SCROLL_DOWN BUTTON_VOL_DOWN
#define MPEG_LEFT BUTTON_LEFT
#define MPEG_RIGHT BUTTON_RIGHT
#define MPEG_UP BUTTON_UP
#define MPEG_DOWN BUTTON_DOWN
#define MPEG_EXIT BUTTON_POWER
#else
#error MPEGPLAYER: Unsupported keypad
#endif
static struct configdata config[] = static struct configdata config[] =
{ {
{TYPE_ENUM, 0, 2, &settings.showfps, "Show FPS", {TYPE_INT, 0, 2, &settings.showfps, "Show FPS", NULL, NULL},
(char *[]){ "No", "Yes" }, NULL}, {TYPE_INT, 0, 2, &settings.limitfps, "Limit FPS", NULL, NULL},
{TYPE_ENUM, 0, 2, &settings.limitfps, "Limit FPS", {TYPE_INT, 0, 2, &settings.skipframes, "Skip frames", NULL, NULL},
(char *[]){ "No", "Yes" }, NULL},
{TYPE_ENUM, 0, 2, &settings.skipframes, "Skip frames",
(char *[]){ "No", "Yes" }, NULL},
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
{TYPE_INT, 0, INT_MAX, &settings.displayoptions, "Display options", {TYPE_INT, 0, INT_MAX, &settings.displayoptions, "Display options",
NULL, NULL}, NULL, NULL},
@ -36,6 +115,7 @@ enum mpeg_menu_ids
MPEG_OPTION_DISPLAY_FPS, MPEG_OPTION_DISPLAY_FPS,
MPEG_OPTION_LIMIT_FPS, MPEG_OPTION_LIMIT_FPS,
MPEG_OPTION_SKIP_FRAMES, MPEG_OPTION_SKIP_FRAMES,
MPEG_OPTION_CLEAR_RESUMES,
MPEG_OPTION_QUIT, MPEG_OPTION_QUIT,
}; };
@ -68,13 +148,250 @@ static void display_options(void)
} }
#endif /* #ifdef TOSHIBA_GIGABEAT_F */ #endif /* #ifdef TOSHIBA_GIGABEAT_F */
void draw_slider(int slider_ypos, int max_val, int current_val)
{
int slider_margin = LCD_WIDTH*12/100; /* 12% */
int slider_width = LCD_WIDTH-(slider_margin*2);
char resume_str[32];
/* max_val and current_val are in half minutes
determine value .0 or .5 to display */
int max_hol = max_val/2;
int max_rem = (max_val-(max_hol*2))*5;
int current_hol = current_val/2;
int current_rem = (current_val-(current_hol*2))*5;
rb->snprintf(resume_str, sizeof(resume_str), "0.0");
rb->lcd_putsxy(slider_margin, slider_ypos, resume_str);
rb->snprintf(resume_str, sizeof(resume_str), "%u.%u", max_hol, max_rem);
rb->lcd_putsxy(LCD_WIDTH-slider_margin-25, slider_ypos, resume_str);
rb->lcd_drawrect(slider_margin, slider_ypos+17, slider_width, 8);
rb->lcd_fillrect(slider_margin, slider_ypos+17,
current_val*slider_width/max_val, 8);
rb->snprintf(resume_str, sizeof(resume_str), "%u.%u", current_hol,
current_rem);
rb->lcd_putsxy(slider_margin+(current_val*slider_width/max_val)-16,
slider_ypos+29, resume_str);
rb->lcd_update_rect(0, slider_ypos, LCD_WIDTH, LCD_HEIGHT-slider_ypos);
}
int get_start_time(int play_time, int in_file)
{
int quit = 0;
int button = 0;
int resume_time = settings.resume_time;
int slider_ypos = LCD_HEIGHT-45;
int seek_rtn;
slider_state = state0;
thumbDelayTimer = *(rb->current_tick);
rb->lcd_clear_display();
rb->lcd_update();
while(quit == 0)
{
button = rb->button_get(false);
switch (button)
{
#if (CONFIG_KEYPAD == GIGABEAT_PAD) || \
(CONFIG_KEYPAD == SANSA_E200_PAD) || \
(CONFIG_KEYPAD == SANSA_C200_PAD)
case MPEG_DOWN:
case MPEG_DOWN | BUTTON_REPEAT:
if ((resume_time -= 20) < 0)
resume_time = 0;
slider_state = state0;
thumbDelayTimer = *(rb->current_tick);
break;
case MPEG_UP:
case MPEG_UP | BUTTON_REPEAT:
if ((resume_time += 20) > play_time)
resume_time = play_time;
slider_state = state0;
thumbDelayTimer = *(rb->current_tick);
break;
#endif
case MPEG_LEFT:
case MPEG_LEFT | BUTTON_REPEAT:
case MPEG_SCROLL_UP:
case MPEG_SCROLL_UP | BUTTON_REPEAT:
if (--resume_time < 0)
resume_time = 0;
slider_state = state0;
thumbDelayTimer = *(rb->current_tick);
break;
case MPEG_RIGHT:
case MPEG_RIGHT | BUTTON_REPEAT:
case MPEG_SCROLL_DOWN:
case MPEG_SCROLL_DOWN | BUTTON_REPEAT:
if (++resume_time > play_time)
resume_time = play_time;
slider_state = state0;
thumbDelayTimer = *(rb->current_tick);
break;
case MPEG_SELECT:
quit = 1;
break;
case MPEG_EXIT:
resume_time = -1;
quit = 1;
break;
default:
if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
{
resume_time = -1;
quit = 1;
}
break;
}
rb->yield();
switch(slider_state)
{
case state0:
rb->lcd_clear_display();
rb->lcd_update();
#ifdef HAVE_LCD_COLOR
if (resume_time > 0)
rb->splash(0, "loading ...");
#endif
slider_state = state1;
break;
case state1:
if (*(rb->current_tick) - thumbDelayTimer > 75)
slider_state = state2;
if (resume_time == 0)
{
seek_rtn = 0;
slider_state = state5;
}
draw_slider(slider_ypos, play_time, resume_time);
break;
case state2:
if ( (seek_rtn = seek_PTS(in_file, resume_time, 1)) >= 0)
slider_state = state3;
else if (seek_rtn == -101)
{
slider_state = state0;
thumbDelayTimer = *(rb->current_tick);
}
else
slider_state = state4;
break;
case state3:
display_thumb(in_file);
draw_slider(slider_ypos, play_time, resume_time);
slider_state = state4;
break;
case state4:
draw_slider(slider_ypos, play_time, resume_time);
slider_state = state5;
break;
case state5:
break;
}
}
return resume_time;
}
int mpeg_start_menu(int play_time, int in_file)
{
int m;
int result = 0;
int menu_quit = 0;
/* add the resume time to the menu display */
char resume_str[32];
int time_hol = (int)(settings.resume_time/2);
int time_rem = ((settings.resume_time%2)==0) ? 0 : 5;
rb->snprintf(resume_str, sizeof(resume_str),
"Resume time (min): %d.%d", time_hol, time_rem);
struct menu_item items[] = {
{ "Play from beginning", NULL },
{ resume_str, NULL },
{ "Set start time (min)", NULL },
{ "Quit mpegplayer", NULL },
};
m = menu_init(rb, items, sizeof(items) / sizeof(*items),
NULL, NULL, NULL, NULL);
rb->button_clear_queue();
while(menu_quit == 0)
{
result = menu_show(m);
switch (result)
{
case 0:
menu_quit = 1;
result = 0;
break;
case 1:
menu_quit = 1;
result = settings.resume_time;
break;
case 2:
#ifndef HAVE_LCD_COLOR
gray_show(true);
#endif
if ((result = get_start_time(play_time, in_file)) >= 0)
menu_quit = 1;
#ifndef HAVE_LCD_COLOR
gray_show(false);
#endif
break;
case 3:
menu_quit = 1;
result = -1;
break;
default:
if (result == MENU_ATTACHED_USB)
{
menu_quit = 1;
result = -1;
}
break;
}
}
menu_exit(m);
settings.resume_time = result;
return (int)result;
}
void clear_resume_count(void)
{
configfile_save(SETTINGS_FILENAME, config,
sizeof(config)/sizeof(*config),
SETTINGS_VERSION);
settings.resume_count = 0;
/* add this place holder so the count is above resume entries */
configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
}
bool mpeg_menu(void) bool mpeg_menu(void)
{ {
int m; int m;
int result; int result;
int menu_quit=0; int menu_quit=0;
static const struct menu_item items[] = { /* add the clear resume option to the menu display */
char clear_str[32];
rb->snprintf(clear_str, sizeof(clear_str),
"Clear all resumes: %u", settings.resume_count);
struct menu_item items[] = {
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
[MPEG_OPTION_DISPLAY_SETTINGS] = [MPEG_OPTION_DISPLAY_SETTINGS] =
{ "Display Options", NULL }, { "Display Options", NULL },
@ -85,6 +402,8 @@ bool mpeg_menu(void)
{ "Limit FPS", NULL }, { "Limit FPS", NULL },
[MPEG_OPTION_SKIP_FRAMES] = [MPEG_OPTION_SKIP_FRAMES] =
{ "Skip frames", NULL }, { "Skip frames", NULL },
[MPEG_OPTION_CLEAR_RESUMES] =
{ clear_str, NULL },
[MPEG_OPTION_QUIT] = [MPEG_OPTION_QUIT] =
{ "Quit mpegplayer", NULL }, { "Quit mpegplayer", NULL },
}; };
@ -115,6 +434,11 @@ bool mpeg_menu(void)
rb->set_option("Skip frames",&settings.skipframes,INT, rb->set_option("Skip frames",&settings.skipframes,INT,
noyes, 2, NULL); noyes, 2, NULL);
break; break;
case MPEG_OPTION_CLEAR_RESUMES:
clear_resume_count();
rb->snprintf(clear_str, sizeof(clear_str),
"Clear all resumes: %u", 0);
break;
case MPEG_OPTION_QUIT: case MPEG_OPTION_QUIT:
default: default:
menu_quit=1; menu_quit=1;
@ -132,48 +456,82 @@ bool mpeg_menu(void)
return (result==MPEG_OPTION_QUIT); return (result==MPEG_OPTION_QUIT);
} }
void init_settings(const char* filename)
void init_settings(void)
{ {
/* Set the default settings */ /* Set the default settings */
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.resume_count = -1;
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
settings.displayoptions = 0; /* No visual effects */ settings.displayoptions = 0; /* No visual effects */
#endif #endif
configfile_init(rb); configfile_init(rb);
if (configfile_load(SETTINGS_FILENAME, config, /* If the config file don't contain resume count
sizeof(config)/sizeof(*config), or the load fails, then rebuild the config file.
SETTINGS_MIN_VERSION This eliminates the worry for older config files
) < 0) having unused data. */
if (((settings.resume_count = configfile_get_value
(SETTINGS_FILENAME, "Resume count")) < 0) ||
(configfile_load(SETTINGS_FILENAME, config,
sizeof(config)/sizeof(*config),
SETTINGS_MIN_VERSION) < 0))
{ {
/* If the loading failed, save a new config file (as the disk is /* Generate a new config file with default values */
already spinning) */
configfile_save(SETTINGS_FILENAME, config, configfile_save(SETTINGS_FILENAME, config,
sizeof(config)/sizeof(*config), sizeof(config)/sizeof(*config),
SETTINGS_VERSION); SETTINGS_VERSION);
} }
/* Keep a copy of the saved version of the settings - so we can check if
the settings have changed when we quit */
old_settings = settings;
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
if ((settings.displayoptions =
configfile_get_value(SETTINGS_FILENAME, "Display options")) < 0)
{
configfile_update_entry(SETTINGS_FILENAME, "Display options",
(settings.displayoptions=0));
}
rb->lcd_yuv_set_options(settings.displayoptions); rb->lcd_yuv_set_options(settings.displayoptions);
#endif #endif
if (settings.resume_count < 0)
{
settings.resume_count = 0;
/* add this place holder so the count is above resume entries */
configfile_update_entry(SETTINGS_FILENAME, "Resume count", 0);
}
rb->strcpy(settings.resume_filename, filename);
/* get the resume time for the current mpeg if it exist */
if ((settings.resume_time = configfile_get_value
(SETTINGS_FILENAME, filename)) < 0)
{
settings.resume_time = 0;
}
} }
void save_settings(void) void save_settings(void)
{ {
/* Save the user settings if they have changed */ configfile_update_entry(SETTINGS_FILENAME, "Show FPS",
if (rb->memcmp(&settings,&old_settings,sizeof(settings))!=0) { settings.showfps);
configfile_save(SETTINGS_FILENAME, config, configfile_update_entry(SETTINGS_FILENAME, "Limit FPS",
sizeof(config)/sizeof(*config), settings.limitfps);
SETTINGS_VERSION); configfile_update_entry(SETTINGS_FILENAME, "Skip frames",
settings.skipframes);
/* Store the settings in old_settings - to check for future changes */ /* If this was a new resume entry then update the total resume count */
old_settings = settings; if (configfile_update_entry(SETTINGS_FILENAME, settings.resume_filename,
settings.resume_time) == 0)
{
configfile_update_entry(SETTINGS_FILENAME, "Resume count",
++settings.resume_count);
} }
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
configfile_update_entry(SETTINGS_FILENAME, "Display options",
settings.displayoptions);
#endif
} }

View file

@ -2,16 +2,23 @@
#include "plugin.h" #include "plugin.h"
struct mpeg_settings { struct mpeg_settings {
int showfps; int showfps; /* flag to display fps */
int limitfps; int limitfps; /* flag to limit fps */
int skipframes; int skipframes; /* flag to skip frames */
int resume_count; /* total # of resumes in config file */
int resume_time; /* resume time for current mpeg (in half minutes) */
char resume_filename[128]; /* filename of current mpeg */
#if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200)
unsigned displayoptions; int displayoptions;
#endif #endif
}; };
extern struct mpeg_settings settings; extern struct mpeg_settings settings;
int get_start_time(int play_time, int in_file);
int mpeg_start_menu(int play_time, int in_file);
bool mpeg_menu(void); bool mpeg_menu(void);
void init_settings(void); void init_settings(const char* filename);
void save_settings(void); void save_settings(void);
void clear_resume_count(void);

File diff suppressed because it is too large Load diff

View file

@ -22,4 +22,6 @@
*/ */
void vo_draw_frame (uint8_t * const * buf); void vo_draw_frame (uint8_t * const * buf);
void vo_draw_frame_thumb (uint8_t * const * buf);
void vo_setup (const mpeg2_sequence_t * sequence); void vo_setup (const mpeg2_sequence_t * sequence);
void vo_cleanup (void);

View file

@ -43,8 +43,7 @@ static int output_height;
void vo_draw_frame (uint8_t * const * buf) void vo_draw_frame (uint8_t * const * buf)
{ {
#ifdef HAVE_LCD_COLOR #ifdef HAVE_LCD_COLOR
rb->lcd_yuv_blit(buf, rb->lcd_yuv_blit(buf, 0,0,image_width,
0,0,image_width,
output_x,output_y,output_width,output_height); output_x,output_y,output_width,output_height);
#else #else
gray_ub_gray_bitmap_part(buf[0],0,0,image_width, gray_ub_gray_bitmap_part(buf[0],0,0,image_width,
@ -60,10 +59,105 @@ void vo_draw_frame (uint8_t * const * buf)
#define SCREEN_HEIGHT LCD_WIDTH #define SCREEN_HEIGHT LCD_WIDTH
#endif #endif
uint8_t* tmpbufa = 0;
uint8_t* tmpbufb = 0;
uint8_t* tmpbufc = 0;
uint8_t* tmpbuf[3];
void vo_draw_frame_thumb (uint8_t * const * buf)
{
int r,c;
#if LCD_WIDTH >= LCD_HEIGHT
for (r=0;r<image_width/2;r++)
for (c=0;c<image_height/2;c++)
*(tmpbuf[0]+c*image_width/2+r) =
*(buf[0]+2*c*image_width+2*r);
for (r=0;r<image_width/4;r++)
for (c=0;c<image_height/4;c++)
{
*(tmpbuf[1]+c*image_width/4+r) =
*(buf[1]+2*c*image_width/2+2*r);
*(tmpbuf[2]+c*image_width/4+r) =
*(buf[2]+2*c*image_width/2+2*r);
}
#else
for (r=0;r<image_width/2;r++)
for (c=0;c<image_height/2;c++)
*(tmpbuf[0]+(image_width/2-1-r)*image_height/2+c) =
*(buf[0]+2*c*image_width+2*r);
for (r=0;r<image_width/4;r++)
for (c=0;c<image_height/4;c++)
{
*(tmpbuf[1]+(image_width/4-1-r)*image_height/4+c) =
*(buf[1]+2*c*image_width/2+2*r);
*(tmpbuf[2]+(image_width/4-1-r)*image_height/4+c) =
*(buf[2]+2*c*image_width/2+2*r);
}
#endif
rb->lcd_clear_display();
rb->lcd_update();
#ifdef HAVE_LCD_COLOR
#ifdef SIMULATOR
#if LCD_WIDTH >= LCD_HEIGHT
rb->lcd_yuv_blit(tmpbuf,0,0,image_width/2,
(LCD_WIDTH-1-image_width/2)/2,
LCD_HEIGHT-50-(image_height/2),
output_width/2,output_height/2);
#else
rb->lcd_yuv_blit(tmpbuf,0,0,image_height/2,
LCD_HEIGHT-50-(image_height/2),
(LCD_WIDTH-1-image_width/2)/2,
output_height/2,output_width/2);
#endif
#else
#if LCD_WIDTH >= LCD_HEIGHT
rb->lcd_yuv_blit(tmpbuf,0,0,image_width/2,
(LCD_WIDTH-1-image_width/2)/2,
LCD_HEIGHT-50-(image_height/2),
output_width/2,output_height/2);
#else
rb->lcd_yuv_blit(tmpbuf,0,0,image_height/2,
LCD_HEIGHT-50-(image_height/2),
(LCD_WIDTH-1-image_width/2)/2,
output_height/2,output_width/2);
#endif
#endif
#else
#if LCD_WIDTH >= LCD_HEIGHT
gray_ub_gray_bitmap_part(tmpbuf[0],0,0,image_width/2,
(LCD_WIDTH-1-image_width/2)/2,
LCD_HEIGHT-50-(image_height/2),
output_width/2,output_height/2);
#else
gray_ub_gray_bitmap_part(tmpbuf[0],0,0,image_height/2,
LCD_HEIGHT-50-(image_height/2),
(LCD_WIDTH-1-image_width/2)/2,
output_height/2,output_width/2);
#endif
#endif
}
void vo_setup(const mpeg2_sequence_t * sequence) void vo_setup(const mpeg2_sequence_t * sequence)
{ {
image_width=sequence->width; image_width=sequence->width;
image_height=sequence->height; image_height=sequence->height;
tmpbufa = (uint8_t*)mpeg2_malloc(sizeof(uint8_t)*image_width/2*
image_height/2, -2);
tmpbufb = (uint8_t*)mpeg2_malloc(sizeof(uint8_t)*image_width/4*
image_height/4, -2);
tmpbufc = (uint8_t*)mpeg2_malloc(sizeof(uint8_t)*image_width/4*
image_height/4, -2);
tmpbuf[0] = tmpbufa;
tmpbuf[1] = tmpbufb;
tmpbuf[2] = tmpbufc;
image_chroma_x=image_width/sequence->chroma_width; image_chroma_x=image_width/sequence->chroma_width;
image_chroma_y=image_height/sequence->chroma_height; image_chroma_y=image_height/sequence->chroma_height;
@ -83,3 +177,13 @@ void vo_setup(const mpeg2_sequence_t * sequence)
output_y = (SCREEN_HEIGHT-sequence->display_height)/2; output_y = (SCREEN_HEIGHT-sequence->display_height)/2;
} }
} }
void vo_cleanup(void)
{
if (tmpbufc)
mpeg2_free(tmpbufc);
if (tmpbufb)
mpeg2_free(tmpbufb);
if (tmpbufa)
mpeg2_free(tmpbufa);
}

View file

@ -339,6 +339,8 @@ David Bishop
Hein-Pieter van Braam Hein-Pieter van Braam
Przemysław Hołubowski Przemysław Hołubowski
Stepan Moskovchenko Stepan Moskovchenko
John S. Gwynne
Brian J. Morey
The libmad team The libmad team
The wavpack team The wavpack team

View file

@ -293,6 +293,11 @@ static void button_boost(bool state)
} }
#endif /* HAVE_ADJUSTABLE_CPU_FREQ */ #endif /* HAVE_ADJUSTABLE_CPU_FREQ */
int button_available( void )
{
return queue_count(&button_queue);
}
long button_get(bool block) long button_get(bool block)
{ {
struct event ev; struct event ev;

View file

@ -27,6 +27,7 @@
extern struct event_queue button_queue; extern struct event_queue button_queue;
void button_init (void); void button_init (void);
int button_available(void);
long button_get (bool block); long button_get (bool block);
long button_get_w_tmo(int ticks); long button_get_w_tmo(int ticks);
intptr_t button_get_data(void); intptr_t button_get_data(void);

View file

@ -736,6 +736,11 @@ void button_event(int key, bool pressed)
/* Again copied from real button.c... */ /* Again copied from real button.c... */
int button_available( void )
{
return queue_count(&button_queue);
}
long button_get(bool block) long button_get(bool block)
{ {
struct event ev; struct event ev;