summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/mpegplayer/mpeg_parser.c1
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c14
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.h2
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c190
-rw-r--r--apps/plugins/mpegplayer/video_thread.c6
5 files changed, 181 insertions, 32 deletions
diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c
index 6883916149..5821bd57ab 100644
--- a/apps/plugins/mpegplayer/mpeg_parser.c
+++ b/apps/plugins/mpegplayer/mpeg_parser.c
@@ -1213,6 +1213,7 @@ int parser_init_stream(void)
void parser_close_stream(void)
{
+ str_send_msg(&video_str, STREAM_CLOSE, 0);
stream_remove_streams();
parser_init_state();
}
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index 2a5c4be617..94a375d866 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -275,6 +275,7 @@ static struct configdata config[] =
{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},
@@ -286,6 +287,11 @@ static const struct opt_items noyes[2] = {
{ "Yes", -1 },
};
+static const struct opt_items singleall[2] = {
+ { "Single", -1 },
+ { "All", -1 },
+};
+
static const struct opt_items enabledisable[2] = {
{ "Disable", -1 },
{ "Enable", -1 },
@@ -1191,7 +1197,7 @@ static void mpeg_settings(void)
MENUITEM_STRINGLIST(menu, "Settings", mpeg_menu_sysevent_callback,
"Display Options", "Audio Options",
- "Resume Options", clear_str);
+ "Resume Options", "Play Mode", clear_str);
rb->button_clear_queue();
@@ -1219,6 +1225,11 @@ static void mpeg_settings(void)
resume_options();
break;
+ case MPEG_SETTING_PLAY_MODE:
+ mpeg_set_option("Play mode", &settings.play_mode,
+ INT, singleall, 2, NULL);
+ break;
+
case MPEG_SETTING_CLEAR_RESUMES:
clear_resume_count();
break;
@@ -1239,6 +1250,7 @@ void init_settings(const char* filename)
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 = 0;
#ifdef HAVE_BACKLIGHT_BRIGHTNESS
diff --git a/apps/plugins/mpegplayer/mpeg_settings.h b/apps/plugins/mpegplayer/mpeg_settings.h
index 6c8b69a4ce..0910116615 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.h
+++ b/apps/plugins/mpegplayer/mpeg_settings.h
@@ -62,6 +62,7 @@ enum mpeg_setting_id
MPEG_SETTING_DISPLAY_SETTINGS,
MPEG_SETTING_AUDIO_SETTINGS,
MPEG_SETTING_ENABLE_START_MENU,
+ MPEG_SETTING_PLAY_MODE,
MPEG_SETTING_CLEAR_RESUMES,
};
@@ -83,6 +84,7 @@ struct mpeg_settings {
#if MPEG_OPTION_DITHERING_ENABLED
int displayoptions;
#endif
+ int play_mode; /* play single file or all files in directory */
/* Audio options - simple on/off specification */
int tone_controls;
int channel_modes;
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 513c2f0863..2314d96889 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -372,6 +372,13 @@ CONFIG_KEYPAD == SANSA_M200_PAD
#define MIN_FF_REWIND_STEP (TS_SECOND/2)
#define OSD_MIN_UPDATE_INTERVAL (HZ/2)
+enum video_action
+{
+ VIDEO_STOP = 0,
+ VIDEO_PREV,
+ VIDEO_NEXT,
+};
+
/* OSD status - same order as icon array */
enum osd_status_enum
{
@@ -1452,7 +1459,7 @@ static void osd_stop(void)
osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW);
- osd_show(OSD_HIDE | OSD_NODRAW);
+ osd_show(OSD_HIDE);
stream_stop();
@@ -1496,6 +1503,53 @@ static void osd_seek(int btn)
stream_seek(time, SEEK_SET);
}
+/* has this file the extension .mpg ? */
+static bool is_videofile(const char* file)
+{
+ const char* ext = rb->strrchr(file, '.');
+ if (ext && !rb->strcasecmp(ext, ".mpg"))
+ return true;
+
+ return false;
+}
+
+/* deliver the next/previous video file in the current directory.
+ returns 0 if there is none. */
+static bool get_videofile(int direction, char* videofile, size_t bufsize)
+{
+ struct tree_context *tree = rb->tree_get_context();
+ struct entry *dircache = tree->dircache;
+ int i, step, end, found = 0;
+ char *videoname = rb->strrchr(videofile, '/') + 1;
+ size_t rest = bufsize - (videoname - videofile) - 1;
+
+ if (direction == VIDEO_NEXT) {
+ i = 0;
+ step = 1;
+ end = tree->filesindir;
+ } else {
+ i = tree->filesindir-1;
+ step = -1;
+ end = -1;
+ }
+ for (; i != end; i += step)
+ {
+ const char* name = dircache[i].name;
+ if (!rb->strcmp(name, videoname)) {
+ found = 1;
+ continue;
+ }
+ if (found && rb->strlen(name) <= rest &&
+ !(dircache[i].attr & ATTR_DIRECTORY) && is_videofile(name))
+ {
+ rb->strcpy(videoname, name);
+ return true;
+ }
+ }
+
+ return false;
+}
+
#ifdef HAVE_HEADPHONE_DETECTION
/* Handle SYS_PHONE_PLUGGED/UNPLUGGED */
static void osd_handle_phone_plug(bool inserted)
@@ -1531,8 +1585,10 @@ static void osd_handle_phone_plug(bool inserted)
}
#endif
-static void button_loop(void)
+static int button_loop(void)
{
+ int next_action = (settings.play_mode == 0) ? VIDEO_STOP : VIDEO_NEXT;
+
rb->lcd_setfont(FONT_SYSFIXED);
#ifdef HAVE_LCD_COLOR
rb->lcd_set_foreground(LCD_WHITE);
@@ -1550,7 +1606,7 @@ static void button_loop(void)
/* Start playback at the specified starting time */
if (osd_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 */
@@ -1629,6 +1685,8 @@ static void button_loop(void)
result = mpeg_menu();
+ next_action = (settings.play_mode == 0) ? VIDEO_STOP : VIDEO_NEXT;
+
/* The menu can change the font, so restore */
rb->lcd_setfont(FONT_SYSFIXED);
#ifdef HAVE_LCD_COLOR
@@ -1641,6 +1699,7 @@ static void button_loop(void)
switch (result)
{
case MPEG_MENU_QUIT:
+ next_action = VIDEO_STOP;
osd_stop();
break;
@@ -1679,6 +1738,7 @@ static void button_loop(void)
#endif
case ACTION_STD_CANCEL:
{
+ next_action = VIDEO_STOP;
osd_stop();
break;
} /* MPEG_STOP: */
@@ -1718,7 +1778,40 @@ static void button_loop(void)
case MPEG_RC_FF:
#endif
{
- osd_seek(button);
+ int old_button = button;
+ if (settings.play_mode != 0)
+ {
+ /* if button has been released: skip to next/previous file */
+ button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL);
+ }
+ switch (button)
+ {
+ case MPEG_RW | BUTTON_REL:
+ {
+ /* release within 3 seconds: skip to previous file, else
+ start the current video from the beginning */
+ osd_stop();
+ if ( stream_get_resume_time() > 3*TS_SECOND ) {
+ osd_play(0);
+ osd_show(OSD_SHOW);
+ } else {
+ next_action = VIDEO_PREV;
+ }
+ break;
+ }
+ case MPEG_FF | BUTTON_REL:
+ {
+ osd_stop();
+ next_action = VIDEO_NEXT;
+ break;
+ }
+ default:
+ {
+ button = old_button;
+ osd_seek(button);
+ break;
+ }
+ }
break;
} /* MPEG_RW: MPEG_FF: */
@@ -1750,13 +1843,18 @@ static void button_loop(void)
#endif
rb->lcd_setfont(FONT_UI);
+
+ return next_action;
}
enum plugin_status plugin_start(const void* parameter)
{
+ static char videofile[MAX_PATH];
+
int status = PLUGIN_ERROR; /* assume failure */
int result;
int err;
+ bool quit = false;
const char *errstring;
if (parameter == NULL) {
@@ -1777,46 +1875,76 @@ enum plugin_status plugin_start(const void* parameter)
rb->lcd_clear_display();
rb->lcd_update();
+ rb->strcpy(videofile, (const char*) parameter);
+
if (stream_init() < STREAM_OK) {
DEBUGF("Could not initialize streams\n");
} else {
- rb->splash(0, "Loading...");
- init_settings((char*)parameter);
+ while (!quit)
+ {
+ int next_action = VIDEO_STOP;
- err = stream_open((char *)parameter);
+ init_settings(videofile);
+ err = stream_open(videofile);
- if (err >= STREAM_OK) {
- /* start menu */
- rb->lcd_clear_display();
- rb->lcd_update();
- result = mpeg_start_menu(stream_get_duration());
+ 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 (result != MPEG_START_QUIT) {
+ /* Enter button loop and process UI */
+ next_action = button_loop();
+ }
- stream_close();
+ stream_close();
- rb->lcd_clear_display();
- rb->lcd_update();
+ rb->lcd_clear_display();
+ rb->lcd_update();
- save_settings();
- status = PLUGIN_OK;
+ save_settings();
+ status = PLUGIN_OK;
- mpeg_menu_sysevent_handle();
- } else {
- DEBUGF("Could not open %s\n", (char*)parameter);
- switch (err)
+ mpeg_menu_sysevent_handle();
+ } else {
+ DEBUGF("Could not open %s\n", videofile);
+ switch (err)
+ {
+ case STREAM_UNSUPPORTED:
+ errstring = "Unsupported format";
+ break;
+ default:
+ errstring = "Error opening file: %d";
+ }
+
+ rb->splashf(HZ*2, errstring, err);
+ status = PLUGIN_ERROR;
+ }
+
+ /* return value of button_loop says, what's next */
+ switch (next_action)
+ {
+ case VIDEO_NEXT:
{
- case STREAM_UNSUPPORTED:
- errstring = "Unsupported format";
+ if (!get_videofile(VIDEO_NEXT, videofile, sizeof(videofile))) {
+ /* quit after finished the last videofile */
+ quit = true;
+ }
break;
- default:
- errstring = "Error opening file: %d";
+ }
+ case VIDEO_PREV:
+ {
+ get_videofile(VIDEO_PREV, videofile, sizeof(videofile));
+ /* if there is no previous file, play the same videofile */
+ break;
+ }
+ case VIDEO_STOP:
+ {
+ quit = true;
+ break;
+ }
}
-
- rb->splashf(HZ*2, errstring, err);
}
}
diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c
index 8feacbdef2..4ccdc8b844 100644
--- a/apps/plugins/mpegplayer/video_thread.c
+++ b/apps/plugins/mpegplayer/video_thread.c
@@ -503,6 +503,12 @@ static void video_thread_msg(struct video_thread_data *td)
reply = true;
break;
+ case STREAM_CLOSE:
+ vo_cleanup();
+ mpeg2_close(td->mpeg2dec);
+ reply = true;
+ break;
+
case VIDEO_DISPLAY_IS_VISIBLE:
reply = vo_is_visible();
break;