diff options
Diffstat (limited to 'apps/plugins/mpegplayer/mpegplayer.c')
-rw-r--r-- | apps/plugins/mpegplayer/mpegplayer.c | 403 |
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 | ||
841 | static 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 | |||
838 | static void osd_schedule_refresh(unsigned refresh) | 852 | static 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 ;) |
1217 | static uint32_t osd_ff_rw(int btn, unsigned refresh) | 1231 | * Returns last button code |
1232 | */ | ||
1233 | static 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 | ||
1349 | static int osd_status(void) | 1336 | /* Return adjusted STREAM_* status */ |
1337 | static 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 | * |
1486 | static 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 | */ | ||
1484 | static 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 | */ | ||
1524 | static 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. */ |
1541 | static bool get_videofile(int direction, char* videofile, size_t bufsize) | 1580 | static 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 | } |