diff -u -r apps/plugins/mpegplayer/mpegplayer.c apps/plugins/mpegplayer/mpegplayer.c --- apps/plugins/mpegplayer/mpegplayer.c 2008-01-28 06:00:12.000000000 +0100 +++ apps/plugins/mpegplayer/mpegplayer.c 2008-02-14 08:42:30.000000000 +0100 @@ -168,6 +168,7 @@ #elif CONFIG_KEYPAD == SANSA_E200_PAD #define MPEG_MENU BUTTON_SELECT +#define MPEG_MENU2 BUTTON_DOWN #define MPEG_STOP BUTTON_POWER #define MPEG_PAUSE BUTTON_UP #define MPEG_VOLDOWN BUTTON_SCROLL_BACK @@ -210,6 +211,12 @@ #define MIN_FF_REWIND_STEP (TS_SECOND/2) #define WVS_MIN_UPDATE_INTERVAL (HZ/2) +#define VIDEO_PREV 0 +#define VIDEO_NEXT 1 +#define VIDEO_STOP 2 +#define VIDEO_SAME 3 +#define VIDEO_CONT 4 + /* WVS status - same order as icon array */ enum wvs_status_enum { @@ -1268,6 +1275,94 @@ stream_seek(time, SEEK_SET); } +/* has this file the extension .mpg ? */ +bool is_videofile (char* file) +{ + const char* mpg = ".mpg"; + char *extension = rb->strrchr(file, '.'); + if ( extension && !rb->strcasecmp(extension, mpg )) return true; + + return false; +} + +/* deliver the (lexically) next video file in the current directory + (or \0 if there is none) */ +static void get_next_video( char* videofile, char* nextfile ) +{ + DIR* dir; + struct dirent *entry; + char dirname[MAX_PATH]; + char* ptr; + int dirlen; + + ptr = rb->strrchr(videofile, '/') + 1; + dirlen = (ptr - videofile); + rb->strncpy(dirname, videofile, dirlen); + dirname[dirlen] = '\0'; + + dir = rb->opendir(dirname); + nextfile[0] = '\0'; + if (dir) + { + while(0 != (entry = rb->readdir(dir))) { + if( is_videofile( entry->d_name ) && + rb->strcmp(entry->d_name, ptr) > 0 ) { + if( nextfile[0] == '\0' || + rb->strcmp(entry->d_name, nextfile) < 0 ) { + rb->strcpy(nextfile, entry->d_name); + } + } + } + rb->closedir(dir); + } + if( nextfile[0] != '\0' ) { + ptr = dirname + dirlen; + rb->strcpy( ptr, nextfile ); + rb->strcpy( nextfile, dirname ); + } + + return; +} + +/* deliver the (lexically) previous video file in the current directory + (or \0 if there is none) */ +static void get_prev_video( char* videofile, char* prevfile ) +{ + DIR* dir; + struct dirent *entry; + char dirname[MAX_PATH]; + char* ptr; + int dirlen; + + ptr = rb->strrchr(videofile, '/') + 1; + dirlen = (ptr - videofile); + rb->strncpy(dirname, videofile, dirlen); + dirname[dirlen] = '\0'; + + dir = rb->opendir(dirname); + prevfile[0] = '\0'; + if (dir) + { + while(0 != (entry = rb->readdir(dir))) { + if( is_videofile(entry->d_name) && + ( rb->strcmp(entry->d_name, ptr) < 0 ) ) { + if( prevfile[0] == '\0' || + rb->strcmp(entry->d_name, prevfile) > 0 ) { + rb->strcpy(prevfile, entry->d_name); + } + } + } + rb->closedir(dir); + } + if( prevfile[0] != '\0' ) { + ptr = dirname + dirlen; + rb->strcpy( ptr, prevfile ); + rb->strcpy( prevfile, dirname ); + } + + return; +} + #ifdef HAVE_HEADPHONE_DETECTION /* Handle SYS_PHONE_PLUGGED/UNPLUGGED */ static void wvs_handle_phone_plug(bool inserted) @@ -1305,8 +1400,14 @@ } #endif -static void button_loop(void) +static int button_loop(void) { + int button = MPEG_STOP; + int old_button; + int next_action; + + next_action = ( settings.play_mode == 0 ) ? VIDEO_STOP : VIDEO_CONT; + rb->lcd_setfont(FONT_SYSFIXED); rb->lcd_clear_display(); rb->lcd_update(); @@ -1320,14 +1421,12 @@ /* Start playback at the specified starting time */ if (wvs_play(settings.resume_time) < STREAM_OK) { rb->splash(HZ*2, "Playback failed"); - return; + return VIDEO_STOP; } /* Gently poll the video player for EOS and handle UI */ while (stream_status() != STREAM_STOPPED) { - int button; - mpeg_menu_sysevent_clear(); button = rb->button_get_w_tmo(WVS_MIN_UPDATE_INTERVAL); @@ -1375,6 +1474,9 @@ #ifdef MPEG_RC_MENU case MPEG_RC_MENU: #endif +#ifdef MPEG_MENU2 + case MPEG_MENU2: +#endif { int state = wvs_halt(); /* save previous state */ int result; @@ -1386,12 +1488,16 @@ result = mpeg_menu(0); + next_action = ( settings.play_mode == 0 ) ? + VIDEO_STOP : VIDEO_CONT; + /* The menu can change the font, so restore */ rb->lcd_setfont(FONT_SYSFIXED); switch (result) { case MPEG_MENU_QUIT: + next_action = VIDEO_STOP; wvs_stop(); break; @@ -1418,6 +1524,7 @@ #endif case ACTION_STD_CANCEL: { + next_action = VIDEO_STOP; wvs_stop(); break; } /* MPEG_STOP: */ @@ -1453,9 +1560,34 @@ case MPEG_RC_FF: #endif { - wvs_seek(button); + /* if button has been released: skip to next/previous file */ + old_button = button; + button = rb->button_get_w_tmo(WVS_MIN_UPDATE_INTERVAL); + switch (button) + { + case MPEG_RW | BUTTON_REL: + { + wvs_stop(); + /* release within 3 seconds: skip to previous file, else + start the current video from the beginning */ + next_action = ( stream_get_resume_time() > 3*TS_SECOND) + ? VIDEO_SAME : VIDEO_PREV; + break; + } + case MPEG_FF | BUTTON_REL: + { + wvs_stop(); + next_action = VIDEO_NEXT; + break; + } + default: + { + button = old_button; + wvs_seek(button); + } + } break; - } /* MPEG_RW: MPEG_FF: */ + } /* MPEG_RW: MPEG_FF: */ #ifdef HAVE_HEADPHONE_DETECTION case SYS_PHONE_PLUGGED: @@ -1621,15 +1621,21 @@ #endif rb->lcd_setfont(FONT_UI); + + return next_action; } enum plugin_status plugin_start(const void* parameter) { int status = PLUGIN_ERROR; /* assume failure */ - int result; + int result = VIDEO_STOP; int err; const char *errstring; + char nextfile[MAX_PATH]; + char videofile[MAX_PATH]; + bool first = true; + if (parameter == NULL) { /* No file = GTFO */ rb->splash(HZ*2, "No File"); @@ -1688,47 +1688,91 @@ rb->lcd_clear_display(); rb->lcd_update(); - if (stream_init() < STREAM_OK) { - DEBUGF("Could not initialize streams\n"); - } else { - rb->splash(0, "Loading..."); - init_settings((char*)parameter); + rb->strcpy(videofile, (char*) parameter); - err = stream_open((char *)parameter); + /* loop */ + while( videofile[0] != '\0' ) { - if (err >= STREAM_OK) { - /* start menu */ - rb->lcd_clear_display(); - rb->lcd_update(); - result = mpeg_start_menu(stream_get_duration()); - - if (result != MPEG_START_QUIT) { - /* Enter button loop and process UI */ - button_loop(); + if (stream_init() < STREAM_OK) { + DEBUGF("Could not initialize streams\n"); + } else { + if( first ) { + rb->splash(0, "Loading..."); + first = false; } - stream_close(); + init_settings(videofile); - rb->lcd_clear_display(); - rb->lcd_update(); + err = stream_open(videofile); - save_settings(); /* Save settings (if they have changed) */ - status = PLUGIN_OK; + if (err >= STREAM_OK) { + /* start menu */ + rb->lcd_clear_display(); + rb->lcd_update(); + result = mpeg_start_menu(stream_get_duration()); - mpeg_menu_sysevent_handle(); - } else { - DEBUGF("Could not open %s\n", (char*)parameter); - switch (err) - { - case STREAM_UNSUPPORTED: - errstring = "Unsupported format"; - break; - default: - errstring = "Error opening file: %d"; - } + if (result != MPEG_START_QUIT) { + /* Enter button loop and process UI */ + result = button_loop(); + } else { + result = VIDEO_STOP; + } - rb->splashf(HZ*2, errstring, err); + stream_close(); + + rb->lcd_clear_display(); + rb->lcd_update(); + + save_settings(); /* Save settings (if they have changed) */ + status = PLUGIN_OK; + + mpeg_menu_sysevent_handle(); + } else { + DEBUGF("Could not open %s\n", (char*)parameter); + switch (err) + { + case STREAM_UNSUPPORTED: + errstring = "Unsupported format"; + break; + default: + errstring = "Error opening file: %d"; + } + + rb->splash(HZ*2, errstring); + } + } + + stream_exit(); + + /* return value of button_loop says, what's next */ + switch (result) + { + case VIDEO_CONT: + case VIDEO_NEXT: + { + get_next_video( videofile, nextfile ); + rb->strcpy( videofile, nextfile ); + break; + } + case VIDEO_PREV: + { + get_prev_video( videofile, nextfile ); + /* if there is no previous file, play the same videofile */ + if( nextfile[0] != 0 ) rb->strcpy( videofile, nextfile ); + break; } + case VIDEO_STOP: + { + videofile[0] = '\0'; + break; + } + case VIDEO_SAME: + { + /* let the videofile unchanged */ + break ; + } + } + } #if defined(HAVE_LCD_MODES) @@ -1737,8 +1781,6 @@ #endif #endif - stream_exit(); - rb->talk_disable(false); return status; } diff -u -r apps/plugins/mpegplayer/mpeg_settings.c apps/plugins/mpegplayer/mpeg_settings.c --- apps/plugins/mpegplayer/mpeg_settings.c 2008-02-01 06:00:23.000000000 +0100 +++ apps/plugins/mpegplayer/mpeg_settings.c 2008-02-14 08:56:20.000000000 +0100 @@ -213,6 +213,7 @@ {TYPE_INT, 0, 2, { .int_p = &settings.crossfeed }, "Crossfeed", NULL}, {TYPE_INT, 0, 2, { .int_p = &settings.equalizer }, "Equalizer", NULL}, {TYPE_INT, 0, 2, { .int_p = &settings.dithering }, "Dithering", NULL}, + {TYPE_INT, 0, 2, { .int_p = &settings.play_mode }, "Play mode", NULL}, #ifdef HAVE_BACKLIGHT_BRIGHTNESS {TYPE_INT, -1, INT_MAX, { .int_p = &settings.backlight_brightness }, "Backlight brightness", NULL}, @@ -121,6 +122,11 @@ { "Yes", -1 }, }; +static const struct opt_items dirfile[2] = { + { "File", -1 }, + { "Directory", -1 }, +}; + static const struct opt_items enabledisable[2] = { { "Disable", -1 }, { "Enable", -1 }, @@ -928,6 +934,8 @@ { "Resume Options", NULL }, [MPEG_MENU_CLEAR_RESUMES] = { clear_str, NULL }, + [MPEG_MENU_PLAY_MODE] = + { "Play mode", NULL }, [MPEG_MENU_QUIT] = { "Quit mpegplayer", NULL }, }; @@ -970,6 +978,11 @@ clear_resume_count(); break; + case MPEG_MENU_PLAY_MODE: + mpeg_set_option("Play mode", + &settings.play_mode, INT, dirfile, 2, NULL); + break; + case MPEG_MENU_QUIT: default: menu_quit = true; @@ -997,6 +1010,7 @@ settings.showfps = 0; /* Do not show FPS */ settings.limitfps = 1; /* Limit FPS */ settings.skipframes = 1; /* Skip frames */ + settings.play_mode = 0; /* Play single video */ settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */ settings.resume_count = -1; #if MPEG_OPTION_DITHERING_ENABLED @@ -1057,6 +1071,8 @@ settings.limitfps); configfile_update_entry(SETTINGS_FILENAME, "Skip frames", settings.skipframes); + configfile_update_entry(SETTINGS_FILENAME, "Play mode", + settings.play_mode); configfile_update_entry(SETTINGS_FILENAME, "Resume options", settings.resume_options); diff -u -r apps/plugins/mpegplayer/mpeg_settings.h apps/plugins/mpegplayer/mpeg_settings.h --- apps/plugins/mpegplayer/mpeg_settings.h 2008-02-01 06:00:23.000000000 +0100 +++ apps/plugins/mpegplayer/mpeg_settings.h 2008-02-14 08:48:49.000000000 +0100 @@ -58,6 +58,7 @@ MPEG_MENU_AUDIO_SETTINGS, MPEG_MENU_ENABLE_START_MENU, MPEG_MENU_CLEAR_RESUMES, + MPEG_MENU_PLAY_MODE, MPEG_MENU_QUIT, }; @@ -68,6 +69,7 @@ int resume_options; /* type of resume action at start */ int resume_count; /* total # of resumes in config file */ int resume_time; /* resume time for current mpeg (in half minutes) */ + int play_mode; /* play single file or all files in directory */ char resume_filename[MAX_PATH]; /* filename of current mpeg */ #if MPEG_OPTION_DITHERING_ENABLED int displayoptions;