diff options
Diffstat (limited to 'apps/plugins/mpegplayer/mpegplayer.c')
-rw-r--r-- | apps/plugins/mpegplayer/mpegplayer.c | 190 |
1 files changed, 159 insertions, 31 deletions
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 | ||
375 | enum 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 */ |
376 | enum osd_status_enum | 383 | enum 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 ? */ | ||
1507 | static 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. */ | ||
1518 | static 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 */ |
1501 | static void osd_handle_phone_plug(bool inserted) | 1555 | static 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 | ||
1534 | static void button_loop(void) | 1588 | static 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 | ||
1755 | enum plugin_status plugin_start(const void* parameter) | 1850 | enum 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 | ||