Index: apps/plugins/mpegplayer/mpegplayer.c =================================================================== --- apps/plugins/mpegplayer/mpegplayer.c (revision 14238) +++ apps/plugins/mpegplayer/mpegplayer.c (working copy) @@ -115,6 +115,7 @@ /* button definitions */ #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define MPEG_SELECT BUTTON_ON #define MPEG_MENU BUTTON_MODE #define MPEG_STOP BUTTON_OFF #define MPEG_PAUSE BUTTON_ON @@ -123,6 +124,7 @@ #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD) +#define MPEG_SELECT BUTTON_SELECT #define MPEG_MENU BUTTON_MENU #define MPEG_PAUSE (BUTTON_PLAY | BUTTON_REL) #define MPEG_STOP (BUTTON_PLAY | BUTTON_REPEAT) @@ -130,6 +132,7 @@ #define MPEG_VOLUP BUTTON_SCROLL_FWD #elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD +#define MPEG_SELECT BUTTON_PLAY #define MPEG_MENU (BUTTON_REC | BUTTON_REL) #define MPEG_STOP BUTTON_POWER #define MPEG_PAUSE BUTTON_PLAY @@ -137,6 +140,7 @@ #define MPEG_VOLUP BUTTON_UP #elif CONFIG_KEYPAD == GIGABEAT_PAD +#define MPEG_SELECT BUTTON_SELECT #define MPEG_MENU BUTTON_MENU #define MPEG_STOP BUTTON_POWER #define MPEG_PAUSE BUTTON_SELECT @@ -146,6 +150,7 @@ #define MPEG_VOLUP2 BUTTON_VOL_UP #elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define MPEG_SELECT BUTTON_PLAY #define MPEG_MENU (BUTTON_REW | BUTTON_REL) #define MPEG_STOP BUTTON_POWER #define MPEG_PAUSE BUTTON_PLAY @@ -153,6 +158,7 @@ #define MPEG_VOLUP BUTTON_SCROLL_UP #elif CONFIG_KEYPAD == SANSA_E200_PAD +#define MPEG_SELECT BUTTON_SELECT #define MPEG_MENU BUTTON_SELECT #define MPEG_STOP BUTTON_POWER #define MPEG_PAUSE BUTTON_UP @@ -353,6 +359,7 @@ #define MPA_MAX_FRAME_SIZE 1729 /* Largest frame - MPEG1, Layer II, 384kbps, 32kHz, pad */ #define MPABUF_SIZE (64*1024 + ALIGN_UP(MPA_MAX_FRAME_SIZE + 2*MAD_BUFFER_GUARD, 4)) #define LIBMPEG2BUFFER_SIZE (2*1024*1024) +#define READBLOCK_SIZE (128*1024) /* 65536+6 is required since each PES has a 6 byte header with a 16 bit packet length field */ #define MPEG_GUARDBUF_SIZE (64*1024+1024) /* Keep a bit extra - excessive for now */ @@ -378,6 +385,31 @@ static mad_fixed_t mad_frame_overlap[2][32][18]; /* 4608 bytes */ #endif +static char resumefile[MAX_PATH]; +static uint32_t filestartposition= 0; +static uint32_t filecurrentposition=0; + +static void saveresumeposition(uint32_t savepos) { + int rfd; + + if (savepos<1) + { + return; + } + + rfd = rb->open(resumefile, O_WRONLY|O_CREAT); + if (rfd<0) + { + rb->splash( 100, "Can't open %s for writing!", resumefile ); + rb->sleep(HZ*3); + rb->lcd_clear_display(); + rb->lcd_update(); + } + rb->fdprintf(rfd,"%lu",savepos); + rb->close(rfd); +} + + static void init_mad(void* mad_frame_overlap) { rb->memset(&stream, 0, sizeof(struct mad_stream)); @@ -1527,7 +1559,7 @@ } case STATE_SLICE: - case STATE_END: + case STATE_END: case STATE_INVALID_END: { int32_t offset; /* Tick adjustment to keep sync */ @@ -1765,6 +1797,14 @@ uint8_t* buffer; size_t file_remaining; size_t disk_buf_len; + + int button; + uint32_t fileresumeposition; + int resumefilehandle; + char templine[80]; + int resumepercent; + int i; + #ifndef HAVE_LCD_COLOR long graysize; int grayscales; @@ -1842,6 +1882,7 @@ /* Open the video file */ in_file = rb->open((char*)parameter,O_RDONLY); + file_remaining = rb->filesize(in_file); if (in_file < 0){ //fprintf(stderr,"Could not open %s\n",argv[1]); @@ -1869,12 +1910,83 @@ rb->cpu_boost(true); #endif + /* Establish the name to be used for the resume data */ + rb->snprintf(resumefile,sizeof(resumefile),"%s.resume",(char*)parameter); + /* From this point on we've altered settings, colors, cpu_boost, etc. and cannot just return PLUGIN_ERROR - instead drop though to cleanup code */ init_settings(); + + if (settings.resume!=0) + { + /* Open the resume file if present*/ + resumefilehandle = rb->open(resumefile,O_RDONLY); + if (resumefilehandle > -1) + { + rb->read_line(resumefilehandle, templine, sizeof(templine)); + filestartposition=rb->atoi(templine); + } + rb->close(resumefilehandle); + /* delete existing resume file */ + rb->remove(resumefile); + + if (filestartposition>0) + { + resumepercent=(int)(filestartposition/(file_remaining/100)); + if (settings.resume==2) + { + if ((resumepercent>0) && (resumepercent<=100)) + { + rb->snprintf(templine,sizeof(templine),"Resume playback at %d%%?",resumepercent); + } + else + { + rb->snprintf(templine,sizeof(templine),"Resume playback at <1%%?"); + } + + FOR_NB_SCREENS(i) + { + rb->screens[i]->clear_display(); + rb->screens[i]->putsxy(0,40, templine); + rb->screens[i]->putsxy(0,70, "Press SELECT to resume or"); + rb->screens[i]->putsxy(0,85, "any other key to restart video."); + rb->screens[i]->update(); + } + rb->button_clear_queue(); + button=rb->button_get(true); + switch (button) + { + case MPEG_SELECT: + break; + + default: + filestartposition=0; + break; + } + } + if (filestartposition==0) + { + rb->splash( 50, "Restarting video..."); + } + else + { + if ((resumepercent>0) && (resumepercent<=100)) + { + rb->splash( 50, "Resuming video at %d%%...",resumepercent); + } + else + { + rb->splash( 50, "Resuming video at <1%%..."); + } + } + rb->sleep(HZ*1); + } + } + rb->lcd_clear_display(); + /* Msg queue init - no need for queue_remove since it's not a registered queue */ rb->queue_init( &msg_queue, false ); @@ -1885,9 +1997,15 @@ file_remaining = rb->filesize(in_file); disk_buf_end = buffer + buffer_size-MPEG_GUARDBUF_SIZE; + + if (filestartposition>0) + { + filecurrentposition=rb->lseek(in_file, filestartposition, SEEK_CUR); + file_remaining -= filestartposition; + } /* Read some stream data */ - disk_buf_len = rb->read (in_file, buffer, MPEG_LOW_WATERMARK); + disk_buf_len = rb->read (in_file, buffer, READBLOCK_SIZE); DEBUGF("Initial Buffering - %d bytes\n",(int)disk_buf_len); disk_buf = buffer; @@ -1947,7 +2065,8 @@ while (( bytes_to_read > 0) && (file_remaining > 0) && ((audio_str.status >= 0) || (video_str.status >= 0))) { size_t n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read)); - + + filecurrentposition+=n; bytes_to_read -= n; file_remaining -= n; @@ -1996,6 +2115,18 @@ rb->cpu_boost(false); #endif + if ((video_str.curr_packet==NULL) || (audio_str.curr_packet==NULL)) + { + rb->splash(50,"* End of video *"); + rb->sleep(HZ*1); + } + else + { + fileresumeposition=((filecurrentposition-video_str.buffer_remaining)/(READBLOCK_SIZE))*(READBLOCK_SIZE); + fileresumeposition-=READBLOCK_SIZE; + saveresumeposition(fileresumeposition); + } + save_settings(); /* Save settings (if they have changed) */ rb->pcm_set_frequency(HW_SAMPR_DEFAULT); Index: apps/plugins/mpegplayer/mpeg_settings.c =================================================================== --- apps/plugins/mpegplayer/mpeg_settings.c (revision 14238) +++ apps/plugins/mpegplayer/mpeg_settings.c (working copy) @@ -16,12 +16,14 @@ static char* showfps_options[] = {"No", "Yes"}; static char* limitfps_options[] = {"No", "Yes"}; static char* skipframes_options[] = {"No", "Yes"}; +static char* resume_options[] = {"Never", "Always","Prompt"}; static struct configdata config[] = { {TYPE_ENUM, 0, 2, &settings.showfps, "Show FPS", showfps_options, NULL}, {TYPE_ENUM, 0, 2, &settings.limitfps, "Limit FPS", limitfps_options, NULL}, {TYPE_ENUM, 0, 2, &settings.skipframes, "Skip frames", skipframes_options, NULL}, + {TYPE_ENUM, 0, 3, &settings.resume, "Resume video", resume_options, NULL}, }; bool mpeg_menu(void) @@ -34,11 +36,18 @@ { "No", -1 }, { "Yes", -1 }, }; + + static const struct opt_items noyesprompt[3] = { + { "Never", -1 }, + { "Always", -1 }, + { "Prompt", -1 }, + }; static const struct menu_item items[] = { { "Display FPS", NULL }, { "Limit FPS", NULL }, { "Skip frames", NULL }, + { "Resume video", NULL }, { "Quit mpegplayer", NULL }, }; @@ -64,10 +73,14 @@ rb->set_option("Skip frames",&settings.skipframes,INT, noyes, 2, NULL); break; + case 3: /* Resume video */ + rb->set_option("Resume video",&settings.resume,INT, + noyesprompt, 3, NULL); + break; default: menu_quit=1; if (result == MENU_ATTACHED_USB) - result = 3; + result = 4; break; } } @@ -77,7 +90,7 @@ rb->lcd_clear_display(); rb->lcd_update(); - return (result==3); + return (result==4); } @@ -87,6 +100,7 @@ settings.showfps = 0; /* Do not show FPS */ settings.limitfps = 1; /* Limit FPS */ settings.skipframes = 1; /* Skip frames */ + settings.resume = 2; /* Resume video - PROMPT */ configfile_init(rb); Index: apps/plugins/mpegplayer/mpeg_settings.h =================================================================== --- apps/plugins/mpegplayer/mpeg_settings.h (revision 14238) +++ apps/plugins/mpegplayer/mpeg_settings.h (working copy) @@ -5,6 +5,7 @@ int showfps; int limitfps; int skipframes; + int resume; }; extern struct mpeg_settings settings;