summaryrefslogtreecommitdiff
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)
1213 1213
1214void parser_close_stream(void) 1214void parser_close_stream(void)
1215{ 1215{
1216 str_send_msg(&video_str, STREAM_CLOSE, 0);
1216 stream_remove_streams(); 1217 stream_remove_streams();
1217 parser_init_state(); 1218 parser_init_state();
1218} 1219}
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[] =
275 {TYPE_INT, 0, 2, { .int_p = &settings.crossfeed }, "Crossfeed", NULL}, 275 {TYPE_INT, 0, 2, { .int_p = &settings.crossfeed }, "Crossfeed", NULL},
276 {TYPE_INT, 0, 2, { .int_p = &settings.equalizer }, "Equalizer", NULL}, 276 {TYPE_INT, 0, 2, { .int_p = &settings.equalizer }, "Equalizer", NULL},
277 {TYPE_INT, 0, 2, { .int_p = &settings.dithering }, "Dithering", NULL}, 277 {TYPE_INT, 0, 2, { .int_p = &settings.dithering }, "Dithering", NULL},
278 {TYPE_INT, 0, 2, { .int_p = &settings.play_mode }, "Play mode", NULL},
278#ifdef HAVE_BACKLIGHT_BRIGHTNESS 279#ifdef HAVE_BACKLIGHT_BRIGHTNESS
279 {TYPE_INT, -1, INT_MAX, { .int_p = &settings.backlight_brightness }, 280 {TYPE_INT, -1, INT_MAX, { .int_p = &settings.backlight_brightness },
280 "Backlight brightness", NULL}, 281 "Backlight brightness", NULL},
@@ -286,6 +287,11 @@ static const struct opt_items noyes[2] = {
286 { "Yes", -1 }, 287 { "Yes", -1 },
287}; 288};
288 289
290static const struct opt_items singleall[2] = {
291 { "Single", -1 },
292 { "All", -1 },
293};
294
289static const struct opt_items enabledisable[2] = { 295static const struct opt_items enabledisable[2] = {
290 { "Disable", -1 }, 296 { "Disable", -1 },
291 { "Enable", -1 }, 297 { "Enable", -1 },
@@ -1191,7 +1197,7 @@ static void mpeg_settings(void)
1191 1197
1192 MENUITEM_STRINGLIST(menu, "Settings", mpeg_menu_sysevent_callback, 1198 MENUITEM_STRINGLIST(menu, "Settings", mpeg_menu_sysevent_callback,
1193 "Display Options", "Audio Options", 1199 "Display Options", "Audio Options",
1194 "Resume Options", clear_str); 1200 "Resume Options", "Play Mode", clear_str);
1195 1201
1196 rb->button_clear_queue(); 1202 rb->button_clear_queue();
1197 1203
@@ -1219,6 +1225,11 @@ static void mpeg_settings(void)
1219 resume_options(); 1225 resume_options();
1220 break; 1226 break;
1221 1227
1228 case MPEG_SETTING_PLAY_MODE:
1229 mpeg_set_option("Play mode", &settings.play_mode,
1230 INT, singleall, 2, NULL);
1231 break;
1232
1222 case MPEG_SETTING_CLEAR_RESUMES: 1233 case MPEG_SETTING_CLEAR_RESUMES:
1223 clear_resume_count(); 1234 clear_resume_count();
1224 break; 1235 break;
@@ -1239,6 +1250,7 @@ void init_settings(const char* filename)
1239 settings.showfps = 0; /* Do not show FPS */ 1250 settings.showfps = 0; /* Do not show FPS */
1240 settings.limitfps = 1; /* Limit FPS */ 1251 settings.limitfps = 1; /* Limit FPS */
1241 settings.skipframes = 1; /* Skip frames */ 1252 settings.skipframes = 1; /* Skip frames */
1253 settings.play_mode = 0; /* Play single video */
1242 settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */ 1254 settings.resume_options = MPEG_RESUME_MENU_ALWAYS; /* Enable start menu */
1243 settings.resume_count = 0; 1255 settings.resume_count = 0;
1244#ifdef HAVE_BACKLIGHT_BRIGHTNESS 1256#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
62 MPEG_SETTING_DISPLAY_SETTINGS, 62 MPEG_SETTING_DISPLAY_SETTINGS,
63 MPEG_SETTING_AUDIO_SETTINGS, 63 MPEG_SETTING_AUDIO_SETTINGS,
64 MPEG_SETTING_ENABLE_START_MENU, 64 MPEG_SETTING_ENABLE_START_MENU,
65 MPEG_SETTING_PLAY_MODE,
65 MPEG_SETTING_CLEAR_RESUMES, 66 MPEG_SETTING_CLEAR_RESUMES,
66}; 67};
67 68
@@ -83,6 +84,7 @@ struct mpeg_settings {
83#if MPEG_OPTION_DITHERING_ENABLED 84#if MPEG_OPTION_DITHERING_ENABLED
84 int displayoptions; 85 int displayoptions;
85#endif 86#endif
87 int play_mode; /* play single file or all files in directory */
86 /* Audio options - simple on/off specification */ 88 /* Audio options - simple on/off specification */
87 int tone_controls; 89 int tone_controls;
88 int channel_modes; 90 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
372#define MIN_FF_REWIND_STEP (TS_SECOND/2) 372#define MIN_FF_REWIND_STEP (TS_SECOND/2)
373#define OSD_MIN_UPDATE_INTERVAL (HZ/2) 373#define OSD_MIN_UPDATE_INTERVAL (HZ/2)
374 374
375enum video_action
376{
377 VIDEO_STOP = 0,
378 VIDEO_PREV,
379 VIDEO_NEXT,
380};
381
375/* OSD status - same order as icon array */ 382/* OSD status - same order as icon array */
376enum osd_status_enum 383enum osd_status_enum
377{ 384{
@@ -1452,7 +1459,7 @@ static void osd_stop(void)
1452 1459
1453 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); 1460 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
1454 osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW); 1461 osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW);
1455 osd_show(OSD_HIDE | OSD_NODRAW); 1462 osd_show(OSD_HIDE);
1456 1463
1457 stream_stop(); 1464 stream_stop();
1458 1465
@@ -1496,6 +1503,53 @@ static void osd_seek(int btn)
1496 stream_seek(time, SEEK_SET); 1503 stream_seek(time, SEEK_SET);
1497} 1504}
1498 1505
1506/* has this file the extension .mpg ? */
1507static bool is_videofile(const char* file)
1508{
1509 const char* ext = rb->strrchr(file, '.');
1510 if (ext && !rb->strcasecmp(ext, ".mpg"))
1511 return true;
1512
1513 return false;
1514}
1515
1516/* deliver the next/previous video file in the current directory.
1517 returns 0 if there is none. */
1518static bool get_videofile(int direction, char* videofile, size_t bufsize)
1519{
1520 struct tree_context *tree = rb->tree_get_context();
1521 struct entry *dircache = tree->dircache;
1522 int i, step, end, found = 0;
1523 char *videoname = rb->strrchr(videofile, '/') + 1;
1524 size_t rest = bufsize - (videoname - videofile) - 1;
1525
1526 if (direction == VIDEO_NEXT) {
1527 i = 0;
1528 step = 1;
1529 end = tree->filesindir;
1530 } else {
1531 i = tree->filesindir-1;
1532 step = -1;
1533 end = -1;
1534 }
1535 for (; i != end; i += step)
1536 {
1537 const char* name = dircache[i].name;
1538 if (!rb->strcmp(name, videoname)) {
1539 found = 1;
1540 continue;
1541 }
1542 if (found && rb->strlen(name) <= rest &&
1543 !(dircache[i].attr & ATTR_DIRECTORY) && is_videofile(name))
1544 {
1545 rb->strcpy(videoname, name);
1546 return true;
1547 }
1548 }
1549
1550 return false;
1551}
1552
1499#ifdef HAVE_HEADPHONE_DETECTION 1553#ifdef HAVE_HEADPHONE_DETECTION
1500/* Handle SYS_PHONE_PLUGGED/UNPLUGGED */ 1554/* Handle SYS_PHONE_PLUGGED/UNPLUGGED */
1501static void osd_handle_phone_plug(bool inserted) 1555static void osd_handle_phone_plug(bool inserted)
@@ -1531,8 +1585,10 @@ static void osd_handle_phone_plug(bool inserted)
1531} 1585}
1532#endif 1586#endif
1533 1587
1534static void button_loop(void) 1588static int button_loop(void)
1535{ 1589{
1590 int next_action = (settings.play_mode == 0) ? VIDEO_STOP : VIDEO_NEXT;
1591
1536 rb->lcd_setfont(FONT_SYSFIXED); 1592 rb->lcd_setfont(FONT_SYSFIXED);
1537#ifdef HAVE_LCD_COLOR 1593#ifdef HAVE_LCD_COLOR
1538 rb->lcd_set_foreground(LCD_WHITE); 1594 rb->lcd_set_foreground(LCD_WHITE);
@@ -1550,7 +1606,7 @@ static void button_loop(void)
1550 /* Start playback at the specified starting time */ 1606 /* Start playback at the specified starting time */
1551 if (osd_play(settings.resume_time) < STREAM_OK) { 1607 if (osd_play(settings.resume_time) < STREAM_OK) {
1552 rb->splash(HZ*2, "Playback failed"); 1608 rb->splash(HZ*2, "Playback failed");
1553 return; 1609 return VIDEO_STOP;
1554 } 1610 }
1555 1611
1556 /* Gently poll the video player for EOS and handle UI */ 1612 /* Gently poll the video player for EOS and handle UI */
@@ -1629,6 +1685,8 @@ static void button_loop(void)
1629 1685
1630 result = mpeg_menu(); 1686 result = mpeg_menu();
1631 1687
1688 next_action = (settings.play_mode == 0) ? VIDEO_STOP : VIDEO_NEXT;
1689
1632 /* The menu can change the font, so restore */ 1690 /* The menu can change the font, so restore */
1633 rb->lcd_setfont(FONT_SYSFIXED); 1691 rb->lcd_setfont(FONT_SYSFIXED);
1634#ifdef HAVE_LCD_COLOR 1692#ifdef HAVE_LCD_COLOR
@@ -1641,6 +1699,7 @@ static void button_loop(void)
1641 switch (result) 1699 switch (result)
1642 { 1700 {
1643 case MPEG_MENU_QUIT: 1701 case MPEG_MENU_QUIT:
1702 next_action = VIDEO_STOP;
1644 osd_stop(); 1703 osd_stop();
1645 break; 1704 break;
1646 1705
@@ -1679,6 +1738,7 @@ static void button_loop(void)
1679#endif 1738#endif
1680 case ACTION_STD_CANCEL: 1739 case ACTION_STD_CANCEL:
1681 { 1740 {
1741 next_action = VIDEO_STOP;
1682 osd_stop(); 1742 osd_stop();
1683 break; 1743 break;
1684 } /* MPEG_STOP: */ 1744 } /* MPEG_STOP: */
@@ -1718,7 +1778,40 @@ static void button_loop(void)
1718 case MPEG_RC_FF: 1778 case MPEG_RC_FF:
1719#endif 1779#endif
1720 { 1780 {
1721 osd_seek(button); 1781 int old_button = button;
1782 if (settings.play_mode != 0)
1783 {
1784 /* if button has been released: skip to next/previous file */
1785 button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL);
1786 }
1787 switch (button)
1788 {
1789 case MPEG_RW | BUTTON_REL:
1790 {
1791 /* release within 3 seconds: skip to previous file, else
1792 start the current video from the beginning */
1793 osd_stop();
1794 if ( stream_get_resume_time() > 3*TS_SECOND ) {
1795 osd_play(0);
1796 osd_show(OSD_SHOW);
1797 } else {
1798 next_action = VIDEO_PREV;
1799 }
1800 break;
1801 }
1802 case MPEG_FF | BUTTON_REL:
1803 {
1804 osd_stop();
1805 next_action = VIDEO_NEXT;
1806 break;
1807 }
1808 default:
1809 {
1810 button = old_button;
1811 osd_seek(button);
1812 break;
1813 }
1814 }
1722 break; 1815 break;
1723 } /* MPEG_RW: MPEG_FF: */ 1816 } /* MPEG_RW: MPEG_FF: */
1724 1817
@@ -1750,13 +1843,18 @@ static void button_loop(void)
1750#endif 1843#endif
1751 1844
1752 rb->lcd_setfont(FONT_UI); 1845 rb->lcd_setfont(FONT_UI);
1846
1847 return next_action;
1753} 1848}
1754 1849
1755enum plugin_status plugin_start(const void* parameter) 1850enum plugin_status plugin_start(const void* parameter)
1756{ 1851{
1852 static char videofile[MAX_PATH];
1853
1757 int status = PLUGIN_ERROR; /* assume failure */ 1854 int status = PLUGIN_ERROR; /* assume failure */
1758 int result; 1855 int result;
1759 int err; 1856 int err;
1857 bool quit = false;
1760 const char *errstring; 1858 const char *errstring;
1761 1859
1762 if (parameter == NULL) { 1860 if (parameter == NULL) {
@@ -1777,46 +1875,76 @@ enum plugin_status plugin_start(const void* parameter)
1777 rb->lcd_clear_display(); 1875 rb->lcd_clear_display();
1778 rb->lcd_update(); 1876 rb->lcd_update();
1779 1877
1878 rb->strcpy(videofile, (const char*) parameter);
1879
1780 if (stream_init() < STREAM_OK) { 1880 if (stream_init() < STREAM_OK) {
1781 DEBUGF("Could not initialize streams\n"); 1881 DEBUGF("Could not initialize streams\n");
1782 } else { 1882 } else {
1783 rb->splash(0, "Loading..."); 1883 while (!quit)
1784 init_settings((char*)parameter); 1884 {
1885 int next_action = VIDEO_STOP;
1785 1886
1786 err = stream_open((char *)parameter); 1887 init_settings(videofile);
1888 err = stream_open(videofile);
1787 1889
1788 if (err >= STREAM_OK) { 1890 if (err >= STREAM_OK) {
1789 /* start menu */ 1891 /* start menu */
1790 rb->lcd_clear_display(); 1892 rb->lcd_clear_display();
1791 rb->lcd_update(); 1893 rb->lcd_update();
1792 result = mpeg_start_menu(stream_get_duration()); 1894 result = mpeg_start_menu(stream_get_duration());
1793 1895
1794 if (result != MPEG_START_QUIT) { 1896 if (result != MPEG_START_QUIT) {
1795 /* Enter button loop and process UI */ 1897 /* Enter button loop and process UI */
1796 button_loop(); 1898 next_action = button_loop();
1797 } 1899 }
1798 1900
1799 stream_close(); 1901 stream_close();
1800 1902
1801 rb->lcd_clear_display(); 1903 rb->lcd_clear_display();
1802 rb->lcd_update(); 1904 rb->lcd_update();
1803 1905
1804 save_settings(); 1906 save_settings();
1805 status = PLUGIN_OK; 1907 status = PLUGIN_OK;
1806 1908
1807 mpeg_menu_sysevent_handle(); 1909 mpeg_menu_sysevent_handle();
1808 } else { 1910 } else {
1809 DEBUGF("Could not open %s\n", (char*)parameter); 1911 DEBUGF("Could not open %s\n", videofile);
1810 switch (err) 1912 switch (err)
1913 {
1914 case STREAM_UNSUPPORTED:
1915 errstring = "Unsupported format";
1916 break;
1917 default:
1918 errstring = "Error opening file: %d";
1919 }
1920
1921 rb->splashf(HZ*2, errstring, err);
1922 status = PLUGIN_ERROR;
1923 }
1924
1925 /* return value of button_loop says, what's next */
1926 switch (next_action)
1927 {
1928 case VIDEO_NEXT:
1811 { 1929 {
1812 case STREAM_UNSUPPORTED: 1930 if (!get_videofile(VIDEO_NEXT, videofile, sizeof(videofile))) {
1813 errstring = "Unsupported format"; 1931 /* quit after finished the last videofile */
1932 quit = true;
1933 }
1814 break; 1934 break;
1815 default: 1935 }
1816 errstring = "Error opening file: %d"; 1936 case VIDEO_PREV:
1937 {
1938 get_videofile(VIDEO_PREV, videofile, sizeof(videofile));
1939 /* if there is no previous file, play the same videofile */
1940 break;
1941 }
1942 case VIDEO_STOP:
1943 {
1944 quit = true;
1945 break;
1946 }
1817 } 1947 }
1818
1819 rb->splashf(HZ*2, errstring, err);
1820 } 1948 }
1821 } 1949 }
1822 1950
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)
503 reply = true; 503 reply = true;
504 break; 504 break;
505 505
506 case STREAM_CLOSE:
507 vo_cleanup();
508 mpeg2_close(td->mpeg2dec);
509 reply = true;
510 break;
511
506 case VIDEO_DISPLAY_IS_VISIBLE: 512 case VIDEO_DISPLAY_IS_VISIBLE:
507 reply = vo_is_visible(); 513 reply = vo_is_visible();
508 break; 514 break;