summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/mpegplayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/mpegplayer.c')
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c403
1 files changed, 251 insertions, 152 deletions
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 7a2b457aec..d21907f607 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -412,7 +412,9 @@ enum osd_bits
412 OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */ 412 OSD_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */
413 OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */ 413 OSD_NODRAW = 0x8000, /* OR bitflag - don't draw anything */
414 OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */ 414 OSD_SHOW = 0x4000, /* OR bitflag - show the OSD */
415 OSD_HP_PAUSE = 0x2000, 415#ifdef HAVE_HEADPHONE_DETECTION
416 OSD_HP_PAUSE = 0x2000, /* OR bitflag - headphones caused pause */
417#endif
416 OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */ 418 OSD_HIDE = 0x0000, /* hide the OSD (aid readability) */
417 OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */ 419 OSD_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */
418}; 420};
@@ -835,6 +837,18 @@ static void osd_init(void)
835 osd_text_init(); 837 osd_text_init();
836} 838}
837 839
840#ifdef HAVE_HEADPHONE_DETECTION
841static void osd_set_hp_pause_flag(bool set)
842{
843 if (set)
844 osd.flags |= OSD_HP_PAUSE;
845 else
846 osd.flags &= ~OSD_HP_PAUSE;
847}
848#else
849#define osd_set_hp_pause_flag(set)
850#endif /* HAVE_HEADPHONE_DETECTION */
851
838static void osd_schedule_refresh(unsigned refresh) 852static void osd_schedule_refresh(unsigned refresh)
839{ 853{
840 long tick = *rb->current_tick; 854 long tick = *rb->current_tick;
@@ -1213,8 +1227,10 @@ static int osd_get_status(void)
1213 return osd.status & OSD_STATUS_MASK; 1227 return osd.status & OSD_STATUS_MASK;
1214} 1228}
1215 1229
1216/* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;) */ 1230/* Handle Fast-forward/Rewind keys using WPS settings (and some nicked code ;)
1217static uint32_t osd_ff_rw(int btn, unsigned refresh) 1231 * Returns last button code
1232 */
1233static int osd_ff_rw(int btn, unsigned refresh, uint32_t *new_time)
1218{ 1234{
1219 unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step; 1235 unsigned int step = TS_SECOND*rb->global_settings->ff_rewind_min_step;
1220 const long ff_rw_accel = (rb->global_settings->ff_rewind_accel + 3); 1236 const long ff_rw_accel = (rb->global_settings->ff_rewind_accel + 3);
@@ -1224,6 +1240,7 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh)
1224 unsigned int max_step = 0; 1240 unsigned int max_step = 0;
1225 uint32_t ff_rw_count = 0; 1241 uint32_t ff_rw_count = 0;
1226 unsigned status = osd.status; 1242 unsigned status = osd.status;
1243 int new_btn;
1227 1244
1228 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME | 1245 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME |
1229 OSD_REFRESH_TIME); 1246 OSD_REFRESH_TIME);
@@ -1239,9 +1256,8 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh)
1239#ifdef MPEG_RC_FF 1256#ifdef MPEG_RC_FF
1240 case MPEG_RC_FF: 1257 case MPEG_RC_FF:
1241#endif 1258#endif
1242 if (!(btn & BUTTON_REPEAT)) 1259 osd_set_status(OSD_STATUS_FF);
1243 osd_set_status(OSD_STATUS_FF); 1260 new_btn = btn | BUTTON_REPEAT; /* simplify code below */
1244 btn = MPEG_FF | BUTTON_REPEAT; /* simplify code below */
1245 break; 1261 break;
1246 case MPEG_RW: 1262 case MPEG_RW:
1247#ifdef MPEG_RW2 1263#ifdef MPEG_RW2
@@ -1250,103 +1266,75 @@ static uint32_t osd_ff_rw(int btn, unsigned refresh)
1250#ifdef MPEG_RC_RW 1266#ifdef MPEG_RC_RW
1251 case MPEG_RC_RW: 1267 case MPEG_RC_RW:
1252#endif 1268#endif
1253 if (!(btn & BUTTON_REPEAT)) 1269 osd_set_status(OSD_STATUS_RW);
1254 osd_set_status(OSD_STATUS_RW); 1270 new_btn = btn | BUTTON_REPEAT; /* simplify code below */
1255 btn = MPEG_RW | BUTTON_REPEAT; /* simplify code below */
1256 break; 1271 break;
1257 default: 1272 default:
1258 btn = -1; 1273 new_btn = BUTTON_NONE; /* Fail tests below but still do proper exit */
1259 } 1274 }
1260 1275
1261 while (1) 1276 while (1)
1262 { 1277 {
1263 stream_keep_disk_active(); 1278 stream_keep_disk_active();
1264 1279
1265 switch (btn) 1280 if (new_btn == (btn | BUTTON_REPEAT)) {
1266 { 1281 if (osd.status == OSD_STATUS_FF) {
1267 case BUTTON_NONE: 1282 /* fast forwarding, calc max step relative to end */
1268 osd_refresh(OSD_REFRESH_DEFAULT); 1283 max_step = muldiv_uint32(duration - (time + ff_rw_count),
1269 break; 1284 FF_REWIND_MAX_PERCENT, 100);
1270 1285 } else {
1271 case MPEG_FF | BUTTON_REPEAT: 1286 /* rewinding, calc max step relative to start */
1272 case MPEG_RW | BUTTON_REPEAT: 1287 max_step = muldiv_uint32(time - ff_rw_count,
1273#ifdef MPEG_FF2 1288 FF_REWIND_MAX_PERCENT, 100);
1274 case MPEG_FF2 | BUTTON_REPEAT: 1289 }
1275#endif
1276#ifdef MPEG_RW2
1277 case MPEG_RW2 | BUTTON_REPEAT:
1278#endif
1279#ifdef MPEG_RC_FF
1280 case MPEG_RC_FF | BUTTON_REPEAT:
1281 case MPEG_RC_RW | BUTTON_REPEAT:
1282#endif
1283 break;
1284 1290
1285 case MPEG_FF | BUTTON_REL: 1291 max_step = MAX(max_step, MIN_FF_REWIND_STEP);
1286 case MPEG_RW | BUTTON_REL:
1287#ifdef MPEG_FF2
1288 case MPEG_FF2 | BUTTON_REL:
1289#endif
1290#ifdef MPEG_RW2
1291 case MPEG_RW2 | BUTTON_REL:
1292#endif
1293#ifdef MPEG_RC_FF
1294 case MPEG_RC_FF | BUTTON_REL:
1295 case MPEG_RC_RW | BUTTON_REL:
1296#endif
1297 if (osd.status == OSD_STATUS_FF)
1298 time += ff_rw_count;
1299 else if (osd.status == OSD_STATUS_RW)
1300 time -= ff_rw_count;
1301 1292
1302 /* Fall-through */ 1293 if (step > max_step)
1303 case -1: 1294 step = max_step;
1304 default:
1305 osd_schedule_refresh(refresh);
1306 osd_set_status(status);
1307 osd_schedule_refresh(OSD_REFRESH_TIME);
1308 return time;
1309 }
1310 1295
1311 if (osd.status == OSD_STATUS_FF) { 1296 ff_rw_count += step;
1312 /* fast forwarding, calc max step relative to end */
1313 max_step = muldiv_uint32(duration - (time + ff_rw_count),
1314 FF_REWIND_MAX_PERCENT, 100);
1315 } else {
1316 /* rewinding, calc max step relative to start */
1317 max_step = muldiv_uint32(time - ff_rw_count,
1318 FF_REWIND_MAX_PERCENT, 100);
1319 }
1320 1297
1321 max_step = MAX(max_step, MIN_FF_REWIND_STEP); 1298 /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */
1299 step += step >> ff_rw_accel;
1322 1300
1323 if (step > max_step) 1301 if (osd.status == OSD_STATUS_FF) {
1324 step = max_step; 1302 if (duration - time <= ff_rw_count)
1303 ff_rw_count = duration - time;
1325 1304
1326 ff_rw_count += step; 1305 osd.curr_time = time + ff_rw_count;
1306 } else {
1307 if (time <= ff_rw_count)
1308 ff_rw_count = time;
1327 1309
1328 /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */ 1310 osd.curr_time = time - ff_rw_count;
1329 step += step >> ff_rw_accel; 1311 }
1330 1312
1331 if (osd.status == OSD_STATUS_FF) { 1313 osd_refresh(OSD_REFRESH_TIME);
1332 if (duration - time <= ff_rw_count)
1333 ff_rw_count = duration - time;
1334 1314
1335 osd.curr_time = time + ff_rw_count; 1315 new_btn = mpeg_button_get(TIMEOUT_BLOCK);
1336 } else {
1337 if (time <= ff_rw_count)
1338 ff_rw_count = time;
1339
1340 osd.curr_time = time - ff_rw_count;
1341 } 1316 }
1317 else {
1318 if (new_btn == (btn | BUTTON_REL)) {
1319 if (osd.status == OSD_STATUS_FF)
1320 time += ff_rw_count;
1321 else if (osd.status == OSD_STATUS_RW)
1322 time -= ff_rw_count;
1323 }
1342 1324
1343 osd_refresh(OSD_REFRESH_TIME); 1325 *new_time = time;
1326
1327 osd_schedule_refresh(refresh);
1328 osd_set_status(status);
1329 osd_schedule_refresh(OSD_REFRESH_TIME);
1344 1330
1345 btn = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL); 1331 return new_btn;
1332 }
1346 } 1333 }
1347} 1334}
1348 1335
1349static int osd_status(void) 1336/* Return adjusted STREAM_* status */
1337static int osd_stream_status(void)
1350{ 1338{
1351 int status = stream_status(); 1339 int status = stream_status();
1352 1340
@@ -1394,6 +1382,7 @@ static int osd_play(uint32_t time)
1394{ 1382{
1395 int retval; 1383 int retval;
1396 1384
1385 osd_set_hp_pause_flag(false);
1397 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); 1386 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
1398 1387
1399 retval = stream_seek(time, SEEK_SET); 1388 retval = stream_seek(time, SEEK_SET);
@@ -1436,6 +1425,8 @@ static int osd_pause(void)
1436 unsigned refresh = osd.auto_refresh; 1425 unsigned refresh = osd.auto_refresh;
1437 int status = osd_halt(); 1426 int status = osd_halt();
1438 1427
1428 osd_set_hp_pause_flag(false);
1429
1439 if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) { 1430 if (status == STREAM_PLAYING && (refresh & OSD_REFRESH_RESUME)) {
1440 /* Resume pending - change to a still video frame update */ 1431 /* Resume pending - change to a still video frame update */
1441 osd_schedule_refresh(OSD_REFRESH_VIDEO); 1432 osd_schedule_refresh(OSD_REFRESH_VIDEO);
@@ -1454,6 +1445,7 @@ static void osd_resume(void)
1454{ 1445{
1455 /* Cancel video and resume auto refresh - the resyc when starting 1446 /* Cancel video and resume auto refresh - the resyc when starting
1456 * playback will perform those tasks */ 1447 * playback will perform those tasks */
1448 osd_set_hp_pause_flag(false);
1457 osd_backlight_on_video_mode(true); 1449 osd_backlight_on_video_mode(true);
1458 osd_backlight_brightness_video_mode(true); 1450 osd_backlight_brightness_video_mode(true);
1459 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); 1451 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
@@ -1466,6 +1458,7 @@ static void osd_stop(void)
1466{ 1458{
1467 uint32_t resume_time; 1459 uint32_t resume_time;
1468 1460
1461 osd_set_hp_pause_flag(false);
1469 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME); 1462 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
1470 osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW); 1463 osd_set_status(OSD_STATUS_STOPPED | OSD_NODRAW);
1471 osd_show(OSD_HIDE); 1464 osd_show(OSD_HIDE);
@@ -1481,35 +1474,81 @@ static void osd_stop(void)
1481 osd_backlight_brightness_video_mode(false); 1474 osd_backlight_brightness_video_mode(false);
1482} 1475}
1483 1476
1484/* Perform a seek if seeking is possible for this stream - if playing, a delay 1477/* Perform a seek by button if seeking is possible for this stream.
1485 * will be inserted before restarting in case the user decides to seek again */ 1478 *
1486static void osd_seek(int btn) 1479 * A delay will be inserted before restarting in case the user decides to
1480 * seek again soon after.
1481 *
1482 * Returns last button code
1483 */
1484static int osd_seek_btn(int btn)
1487{ 1485{
1488 int status; 1486 int status;
1489 unsigned refresh; 1487 unsigned refresh = 0;
1490 uint32_t time; 1488 uint32_t time;
1491 1489
1492 if (!stream_can_seek()) 1490 if (!stream_can_seek())
1493 return; 1491 return true;
1494 1492
1495 /* Halt playback - not strictly nescessary but nice */ 1493 /* Halt playback - not strictly necessary but nice when doing
1494 * buttons */
1496 status = osd_halt(); 1495 status = osd_halt();
1497 1496
1498 if (status == STREAM_STOPPED) 1497 if (status == STREAM_STOPPED)
1499 return; 1498 return true;
1500 1499
1501 osd_show(OSD_SHOW); 1500 osd_show(OSD_SHOW);
1502 1501
1502 /* Obtain a new playback point according to the buttons */
1503 if (status == STREAM_PLAYING) 1503 if (status == STREAM_PLAYING)
1504 refresh = OSD_REFRESH_RESUME; /* delay resume if playing */ 1504 refresh = OSD_REFRESH_RESUME; /* delay resume if playing */
1505 else 1505 else
1506 refresh = OSD_REFRESH_VIDEO; /* refresh if paused */ 1506 refresh = OSD_REFRESH_VIDEO; /* refresh if paused */
1507 1507
1508 /* Obtain a new playback point */ 1508 btn = osd_ff_rw(btn, refresh, &time);
1509 time = osd_ff_rw(btn, refresh);
1510 1509
1511 /* Tell engine to resume at that time */ 1510 /* Tell engine to resume at that time */
1512 stream_seek(time, SEEK_SET); 1511 stream_seek(time, SEEK_SET);
1512
1513 return btn;
1514}
1515
1516/* Perform a seek by time if seeking is possible for this stream
1517 *
1518 * If playing, the seeking is immediate, otherise a delay is added to showing
1519 * a still if paused in case the user does another seek soon after.
1520 *
1521 * If seeking isn't possible, a time of zero performs a skip to the
1522 * beginning.
1523 */
1524static void osd_seek_time(uint32_t time)
1525{
1526 int status;
1527 unsigned refresh = 0;
1528
1529 if (!stream_can_seek() && time != 0)
1530 return;
1531
1532 stream_wait_status();
1533 status = osd_stream_status();
1534
1535 if (status == STREAM_STOPPED)
1536 return;
1537
1538 if (status == STREAM_PLAYING) /* merely preserve resume */
1539 refresh = osd.auto_refresh & OSD_REFRESH_RESUME;
1540 else
1541 refresh = OSD_REFRESH_VIDEO; /* refresh if paused */
1542
1543 /* Cancel print or resume if pending */
1544 osd_cancel_refresh(OSD_REFRESH_VIDEO | OSD_REFRESH_RESUME);
1545
1546 /* Tell engine to seek to the given time - no state change */
1547 stream_seek(time, SEEK_SET);
1548
1549 osd_update_time();
1550 osd_refresh(OSD_REFRESH_TIME);
1551 osd_schedule_refresh(refresh);
1513} 1552}
1514 1553
1515/* Has this file one of the supported extensions? */ 1554/* Has this file one of the supported extensions? */
@@ -1537,7 +1576,7 @@ static bool is_videofile(const char* file)
1537} 1576}
1538 1577
1539/* deliver the next/previous video file in the current directory. 1578/* deliver the next/previous video file in the current directory.
1540 returns 0 if there is none. */ 1579 returns false if there is none. */
1541static bool get_videofile(int direction, char* videofile, size_t bufsize) 1580static bool get_videofile(int direction, char* videofile, size_t bufsize)
1542{ 1581{
1543 struct tree_context *tree = rb->tree_get_context(); 1582 struct tree_context *tree = rb->tree_get_context();
@@ -1583,11 +1622,12 @@ static void osd_handle_phone_plug(bool inserted)
1583 /* Wait for any incomplete state transition to complete first */ 1622 /* Wait for any incomplete state transition to complete first */
1584 stream_wait_status(); 1623 stream_wait_status();
1585 1624
1586 int status = osd_status(); 1625 int status = osd_stream_status();
1587 1626
1588 if (inserted) { 1627 if (inserted) {
1589 if (rb->global_settings->unplug_mode > 1) { 1628 if (rb->global_settings->unplug_mode > 1) {
1590 if (status == STREAM_PAUSED) { 1629 if (status == STREAM_PAUSED &&
1630 (osd.flags & OSD_HP_PAUSE)) {
1591 osd_resume(); 1631 osd_resume();
1592 } 1632 }
1593 } 1633 }
@@ -1595,6 +1635,8 @@ static void osd_handle_phone_plug(bool inserted)
1595 if (status == STREAM_PLAYING) { 1635 if (status == STREAM_PLAYING) {
1596 osd_pause(); 1636 osd_pause();
1597 1637
1638 osd_set_hp_pause_flag(true);
1639
1598 if (stream_can_seek() && rb->global_settings->unplug_rw) { 1640 if (stream_can_seek() && rb->global_settings->unplug_rw) {
1599 stream_seek(-rb->global_settings->unplug_rw*TS_SECOND, 1641 stream_seek(-rb->global_settings->unplug_rw*TS_SECOND,
1600 SEEK_CUR); 1642 SEEK_CUR);
@@ -1635,12 +1677,7 @@ static int button_loop(void)
1635 /* Gently poll the video player for EOS and handle UI */ 1677 /* Gently poll the video player for EOS and handle UI */
1636 while (stream_status() != STREAM_STOPPED) 1678 while (stream_status() != STREAM_STOPPED)
1637 { 1679 {
1638 int button; 1680 int button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL/2);
1639
1640 mpeg_menu_sysevent_clear();
1641 button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL/2);
1642
1643 button = mpeg_menu_sysevent_callback(button, NULL);
1644 1681
1645 switch (button) 1682 switch (button)
1646 { 1683 {
@@ -1761,6 +1798,7 @@ static int button_loop(void)
1761#endif 1798#endif
1762 case ACTION_STD_CANCEL: 1799 case ACTION_STD_CANCEL:
1763 { 1800 {
1801 cancel_playback:
1764 next_action = VIDEO_STOP; 1802 next_action = VIDEO_STOP;
1765 osd_stop(); 1803 osd_stop();
1766 break; 1804 break;
@@ -1774,7 +1812,7 @@ static int button_loop(void)
1774 case MPEG_RC_PAUSE: 1812 case MPEG_RC_PAUSE:
1775#endif 1813#endif
1776 { 1814 {
1777 int status = osd_status(); 1815 int status = osd_stream_status();
1778 1816
1779 if (status == STREAM_PLAYING) { 1817 if (status == STREAM_PLAYING) {
1780 /* Playing => Paused */ 1818 /* Playing => Paused */
@@ -1789,54 +1827,72 @@ static int button_loop(void)
1789 } /* MPEG_PAUSE*: */ 1827 } /* MPEG_PAUSE*: */
1790 1828
1791 case MPEG_RW: 1829 case MPEG_RW:
1792 case MPEG_FF:
1793#ifdef MPEG_RW2 1830#ifdef MPEG_RW2
1794 case MPEG_RW2: 1831 case MPEG_RW2:
1795#endif 1832#endif
1833#ifdef MPEG_RC_RW
1834 case MPEG_RC_RW:
1835#endif
1836 {
1837 int old_button = button;
1838
1839 /* If button has been released: skip to next/previous file */
1840 button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL);
1841
1842 if ((old_button | BUTTON_REL) == button) {
1843 /* Check current playback position */
1844 osd_update_time();
1845
1846 if (settings.play_mode == 0 || osd.curr_time >= 3*TS_SECOND) {
1847 /* Start the current video from the beginning */
1848 osd_seek_time(0*TS_SECOND);
1849 }
1850 else {
1851 /* Release within 3 seconds of start: skip to previous
1852 * file */
1853 osd_stop();
1854 next_action = VIDEO_PREV;
1855 }
1856 }
1857 else if ((button & ~BUTTON_REPEAT) == old_button) {
1858 button = osd_seek_btn(old_button);
1859 }
1860
1861 if (button == ACTION_STD_CANCEL)
1862 goto cancel_playback; /* jump to stop handling above */
1863
1864 rb->default_event_handler(button);
1865 break;
1866 } /* MPEG_RW: */
1867
1868 case MPEG_FF:
1796#ifdef MPEG_FF2 1869#ifdef MPEG_FF2
1797 case MPEG_FF2: 1870 case MPEG_FF2:
1798#endif 1871#endif
1799#ifdef MPEG_RC_RW 1872#ifdef MPEG_RC_FF
1800 case MPEG_RC_RW:
1801 case MPEG_RC_FF: 1873 case MPEG_RC_FF:
1802#endif 1874#endif
1803 { 1875 {
1804 int old_button = button; 1876 int old_button = button;
1877
1805 if (settings.play_mode != 0) 1878 if (settings.play_mode != 0)
1806 { 1879 button = mpeg_button_get(OSD_MIN_UPDATE_INTERVAL);
1807 /* if button has been released: skip to next/previous file */ 1880
1808 button = rb->button_get_w_tmo(OSD_MIN_UPDATE_INTERVAL); 1881 if ((old_button | BUTTON_REL) == button) {
1809 } 1882 /* If button has been released: skip to next file */
1810 switch (button)
1811 {
1812 case MPEG_RW | BUTTON_REL:
1813 {
1814 /* release within 3 seconds: skip to previous file, else
1815 start the current video from the beginning */
1816 osd_stop();
1817 if ( stream_get_resume_time() > 3*TS_SECOND ) {
1818 osd_play(0);
1819 osd_show(OSD_SHOW);
1820 } else {
1821 next_action = VIDEO_PREV;
1822 }
1823 break;
1824 }
1825 case MPEG_FF | BUTTON_REL:
1826 {
1827 osd_stop(); 1883 osd_stop();
1828 next_action = VIDEO_NEXT; 1884 next_action = VIDEO_NEXT;
1829 break;
1830 }
1831 default:
1832 {
1833 button = old_button;
1834 osd_seek(button);
1835 break;
1836 }
1837 } 1885 }
1886 else if ((button & ~BUTTON_REPEAT) == old_button) {
1887 button = osd_seek_btn(old_button);
1888 }
1889
1890 if (button == ACTION_STD_CANCEL)
1891 goto cancel_playback; /* jump to stop handling above */
1892
1893 rb->default_event_handler(button);
1838 break; 1894 break;
1839 } /* MPEG_RW: MPEG_FF: */ 1895 } /* MPEG_FF: */
1840 1896
1841#ifdef HAVE_HEADPHONE_DETECTION 1897#ifdef HAVE_HEADPHONE_DETECTION
1842 case SYS_PHONE_PLUGGED: 1898 case SYS_PHONE_PLUGGED:
@@ -1849,6 +1905,7 @@ static int button_loop(void)
1849 1905
1850 default: 1906 default:
1851 { 1907 {
1908 osd_refresh(OSD_REFRESH_DEFAULT);
1852 rb->default_event_handler(button); 1909 rb->default_event_handler(button);
1853 break; 1910 break;
1854 } /* default: */ 1911 } /* default: */
@@ -1874,10 +1931,7 @@ enum plugin_status plugin_start(const void* parameter)
1874{ 1931{
1875 static char videofile[MAX_PATH]; 1932 static char videofile[MAX_PATH];
1876 int status = PLUGIN_OK; /* assume success */ 1933 int status = PLUGIN_OK; /* assume success */
1877 int result;
1878 int err;
1879 bool quit = false; 1934 bool quit = false;
1880 const char *errstring;
1881 1935
1882 if (parameter == NULL) { 1936 if (parameter == NULL) {
1883 /* No file = GTFO */ 1937 /* No file = GTFO */
@@ -1904,19 +1958,24 @@ enum plugin_status plugin_start(const void* parameter)
1904 DEBUGF("Could not initialize streams\n"); 1958 DEBUGF("Could not initialize streams\n");
1905 status = PLUGIN_ERROR; 1959 status = PLUGIN_ERROR;
1906 } else { 1960 } else {
1961 int next_action = VIDEO_STOP;
1962 bool get_videofile_says = true;
1963
1907 while (!quit) 1964 while (!quit)
1908 { 1965 {
1909 int next_action = VIDEO_STOP; 1966 int result;
1910 1967
1911 init_settings(videofile); 1968 init_settings(videofile);
1912 err = stream_open(videofile);
1913 1969
1914 if (err >= STREAM_OK) { 1970 result = stream_open(videofile);
1971
1972 if (result >= STREAM_OK) {
1915 /* start menu */ 1973 /* start menu */
1916 rb->lcd_clear_display(); 1974 rb->lcd_clear_display();
1917 rb->lcd_update(); 1975 rb->lcd_update();
1918 result = mpeg_start_menu(stream_get_duration()); 1976 result = mpeg_start_menu(stream_get_duration());
1919 1977
1978 next_action = VIDEO_STOP;
1920 if (result != MPEG_START_QUIT) { 1979 if (result != MPEG_START_QUIT) {
1921 /* Enter button loop and process UI */ 1980 /* Enter button loop and process UI */
1922 next_action = button_loop(); 1981 next_action = button_loop();
@@ -1928,13 +1987,14 @@ enum plugin_status plugin_start(const void* parameter)
1928 rb->lcd_update(); 1987 rb->lcd_update();
1929 1988
1930 save_settings(); 1989 save_settings();
1931
1932 mpeg_menu_sysevent_handle();
1933 } else { 1990 } else {
1934 /* Problem with file; display message about it - not 1991 /* Problem with file; display message about it - not
1935 * considered a plugin error */ 1992 * considered a plugin error */
1993 long tick;
1994 const char *errstring;
1995
1936 DEBUGF("Could not open %s\n", videofile); 1996 DEBUGF("Could not open %s\n", videofile);
1937 switch (err) 1997 switch (result)
1938 { 1998 {
1939 case STREAM_UNSUPPORTED: 1999 case STREAM_UNSUPPORTED:
1940 errstring = "Unsupported format"; 2000 errstring = "Unsupported format";
@@ -1943,12 +2003,45 @@ enum plugin_status plugin_start(const void* parameter)
1943 errstring = "Error opening file: %d"; 2003 errstring = "Error opening file: %d";
1944 } 2004 }
1945 2005
1946 rb->splashf(HZ*2, errstring, err); 2006 tick = *rb->current_tick + HZ*2;
1947 2007
1948 if (settings.play_mode != 0) { 2008 rb->splashf(0, errstring, result);
1949 /* Try the next file if the play mode is not single play */ 2009
1950 next_action = VIDEO_NEXT; 2010 /* Be sure it doesn't get stuck in an unbreakable loop of bad
1951 } 2011 * files, just in case! Otherwise, keep searching in the
2012 * chosen direction until a good one is found. */
2013 while (!quit && TIME_BEFORE(*rb->current_tick, tick))
2014 {
2015 int button = mpeg_button_get(HZ*2);
2016
2017 switch (button)
2018 {
2019 case MPEG_STOP:
2020 case ACTION_STD_CANCEL:
2021 /* Abort the search and exit */
2022 next_action = VIDEO_STOP;
2023 quit = true;
2024 break;
2025
2026 case BUTTON_NONE:
2027 if (settings.play_mode != 0) {
2028 if (next_action == VIDEO_STOP) {
2029 /* Default to next file */
2030 next_action = VIDEO_NEXT;
2031 }
2032 else if (next_action == VIDEO_PREV &&
2033 !get_videofile_says) {
2034 /* Was first file already; avoid endlessly
2035 * retrying it */
2036 next_action = VIDEO_STOP;
2037 }
2038 }
2039 break;
2040
2041 default:
2042 rb->default_event_handler(button);
2043 } /* switch */
2044 } /* while */
1952 } 2045 }
1953 2046
1954 /* return value of button_loop says, what's next */ 2047 /* return value of button_loop says, what's next */
@@ -1956,15 +2049,16 @@ enum plugin_status plugin_start(const void* parameter)
1956 { 2049 {
1957 case VIDEO_NEXT: 2050 case VIDEO_NEXT:
1958 { 2051 {
1959 if (!get_videofile(VIDEO_NEXT, videofile, sizeof(videofile))) { 2052 get_videofile_says = get_videofile(VIDEO_NEXT, videofile,
1960 /* quit after finished the last videofile */ 2053 sizeof(videofile));
1961 quit = true; 2054 /* quit after finished the last videofile */
1962 } 2055 quit = !get_videofile_says;
1963 break; 2056 break;
1964 } 2057 }
1965 case VIDEO_PREV: 2058 case VIDEO_PREV:
1966 { 2059 {
1967 get_videofile(VIDEO_PREV, videofile, sizeof(videofile)); 2060 get_videofile_says = get_videofile(VIDEO_PREV, videofile,
2061 sizeof(videofile));
1968 /* if there is no previous file, play the same videofile */ 2062 /* if there is no previous file, play the same videofile */
1969 break; 2063 break;
1970 } 2064 }
@@ -1974,7 +2068,7 @@ enum plugin_status plugin_start(const void* parameter)
1974 break; 2068 break;
1975 } 2069 }
1976 } 2070 }
1977 } 2071 } /* while */
1978 } 2072 }
1979 2073
1980#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV) 2074#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_YUV)
@@ -1984,5 +2078,10 @@ enum plugin_status plugin_start(const void* parameter)
1984 stream_exit(); 2078 stream_exit();
1985 2079
1986 rb->talk_disable(false); 2080 rb->talk_disable(false);
2081
2082 /* Actually handle delayed processing of system events of interest
2083 * that were captured in other button loops */
2084 mpeg_sysevent_handle();
2085
1987 return status; 2086 return status;
1988} 2087}