diff options
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 412 |
1 files changed, 219 insertions, 193 deletions
diff --git a/apps/playback.c b/apps/playback.c index 563fb741ed..5ac70d17f7 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -705,7 +705,7 @@ static void set_filebuf_watermark(int seconds) | |||
705 | conf_watermark = bytes; | 705 | conf_watermark = bytes; |
706 | } | 706 | } |
707 | 707 | ||
708 | void codec_configure_callback(int setting, void *value) | 708 | static void codec_configure_callback(int setting, void *value) |
709 | { | 709 | { |
710 | switch (setting) { | 710 | switch (setting) { |
711 | case CODEC_SET_FILEBUF_WATERMARK: | 711 | case CODEC_SET_FILEBUF_WATERMARK: |
@@ -748,7 +748,7 @@ void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3)) | |||
748 | track_changed_callback = handler; | 748 | track_changed_callback = handler; |
749 | } | 749 | } |
750 | 750 | ||
751 | void codec_track_changed(void) | 751 | static void codec_track_changed(void) |
752 | { | 752 | { |
753 | track_changed = true; | 753 | track_changed = true; |
754 | queue_post(&audio_queue, AUDIO_TRACK_CHANGED, 0); | 754 | queue_post(&audio_queue, AUDIO_TRACK_CHANGED, 0); |
@@ -756,7 +756,7 @@ void codec_track_changed(void) | |||
756 | 756 | ||
757 | /* Give codecs or file buffering the right amount of processing time | 757 | /* Give codecs or file buffering the right amount of processing time |
758 | to prevent pcm audio buffer from going empty. */ | 758 | to prevent pcm audio buffer from going empty. */ |
759 | void yield_codecs(void) | 759 | static void yield_codecs(void) |
760 | { | 760 | { |
761 | yield(); | 761 | yield(); |
762 | if (!pcm_is_playing() && !paused) | 762 | if (!pcm_is_playing() && !paused) |
@@ -806,7 +806,7 @@ void strip_id3v1_tag(void) | |||
806 | } | 806 | } |
807 | } | 807 | } |
808 | 808 | ||
809 | void audio_fill_file_buffer(void) | 809 | static void audio_fill_file_buffer(void) |
810 | { | 810 | { |
811 | long i, size; | 811 | long i, size; |
812 | int rc; | 812 | int rc; |
@@ -852,20 +852,28 @@ void audio_fill_file_buffer(void) | |||
852 | tracks[track_widx].filerem);*/ | 852 | tracks[track_widx].filerem);*/ |
853 | } | 853 | } |
854 | 854 | ||
855 | bool loadcodec(const char *trackname, bool start_play) | 855 | static int get_codec_base_type(int type) |
856 | { | ||
857 | switch (type) { | ||
858 | case AFMT_MPA_L1: | ||
859 | case AFMT_MPA_L2: | ||
860 | case AFMT_MPA_L3: | ||
861 | return AFMT_MPA_L3; | ||
862 | } | ||
863 | |||
864 | return type; | ||
865 | } | ||
866 | |||
867 | static bool loadcodec(bool start_play) | ||
856 | { | 868 | { |
857 | char msgbuf[80]; | ||
858 | off_t size; | 869 | off_t size; |
859 | unsigned int filetype; | ||
860 | int fd; | 870 | int fd; |
861 | int i, rc; | 871 | int i, rc; |
862 | const char *codec_path; | 872 | const char *codec_path; |
863 | int copy_n; | 873 | int copy_n; |
864 | int prev_track; | 874 | int prev_track; |
865 | 875 | ||
866 | filetype = probe_file_format(trackname); | 876 | switch (tracks[track_widx].id3.codectype) { |
867 | |||
868 | switch (filetype) { | ||
869 | case AFMT_OGG_VORBIS: | 877 | case AFMT_OGG_VORBIS: |
870 | logf("Codec: Vorbis"); | 878 | logf("Codec: Vorbis"); |
871 | codec_path = CODEC_VORBIS; | 879 | codec_path = CODEC_VORBIS; |
@@ -910,20 +918,20 @@ bool loadcodec(const char *trackname, bool start_play) | |||
910 | break; | 918 | break; |
911 | default: | 919 | default: |
912 | logf("Codec: Unsupported"); | 920 | logf("Codec: Unsupported"); |
913 | snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname); | ||
914 | gui_syncsplash(HZ*2, true, msgbuf); | ||
915 | codec_path = NULL; | 921 | codec_path = NULL; |
916 | return false; | 922 | return false; |
917 | } | 923 | } |
918 | 924 | ||
919 | tracks[track_widx].id3.codectype = filetype; | ||
920 | tracks[track_widx].codecsize = 0; | 925 | tracks[track_widx].codecsize = 0; |
921 | 926 | ||
922 | if (!start_play) { | 927 | if (!start_play) { |
923 | prev_track = track_widx - 1; | 928 | prev_track = track_widx - 1; |
924 | if (prev_track < 0) | 929 | if (prev_track < 0) |
925 | prev_track = MAX_TRACK-1; | 930 | prev_track = MAX_TRACK-1; |
926 | if (track_count > 0 && filetype == tracks[prev_track].id3.codectype) { | 931 | if (track_count > 0 && |
932 | get_codec_base_type(tracks[track_widx].id3.codectype) == | ||
933 | get_codec_base_type(tracks[prev_track].id3.codectype)) | ||
934 | { | ||
927 | logf("Reusing prev. codec"); | 935 | logf("Reusing prev. codec"); |
928 | return true; | 936 | return true; |
929 | } | 937 | } |
@@ -943,8 +951,6 @@ bool loadcodec(const char *trackname, bool start_play) | |||
943 | fd = open(codec_path, O_RDONLY); | 951 | fd = open(codec_path, O_RDONLY); |
944 | if (fd < 0) { | 952 | if (fd < 0) { |
945 | logf("Codec doesn't exist!"); | 953 | logf("Codec doesn't exist!"); |
946 | snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", codec_path); | ||
947 | gui_syncsplash(HZ*2, true, msgbuf); | ||
948 | return false; | 954 | return false; |
949 | } | 955 | } |
950 | 956 | ||
@@ -981,7 +987,7 @@ bool loadcodec(const char *trackname, bool start_play) | |||
981 | return true; | 987 | return true; |
982 | } | 988 | } |
983 | 989 | ||
984 | bool read_next_metadata(void) | 990 | static bool read_next_metadata(void) |
985 | { | 991 | { |
986 | int fd; | 992 | int fd; |
987 | char *trackname; | 993 | char *trackname; |
@@ -1010,22 +1016,21 @@ bool read_next_metadata(void) | |||
1010 | * In fact, it might be better not to start filling here, because if user | 1016 | * In fact, it might be better not to start filling here, because if user |
1011 | * is manipulating the playlist a lot, we will just lose battery. */ | 1017 | * is manipulating the playlist a lot, we will just lose battery. */ |
1012 | // filling = true; | 1018 | // filling = true; |
1013 | tracks[next_track].id3.codectype = probe_file_format(trackname); | ||
1014 | status = get_metadata(&tracks[next_track],fd,trackname,v1first); | 1019 | status = get_metadata(&tracks[next_track],fd,trackname,v1first); |
1015 | tracks[next_track].id3.codectype = 0; | ||
1016 | track_changed = true; | 1020 | track_changed = true; |
1017 | close(fd); | 1021 | close(fd); |
1018 | 1022 | ||
1019 | return status; | 1023 | return status; |
1020 | } | 1024 | } |
1021 | 1025 | ||
1022 | bool audio_load_track(int offset, bool start_play, int peek_offset) | 1026 | static bool audio_load_track(int offset, bool start_play, int peek_offset) |
1023 | { | 1027 | { |
1024 | char *trackname; | 1028 | char *trackname; |
1025 | int fd = -1; | 1029 | int fd = -1; |
1026 | off_t size; | 1030 | off_t size; |
1027 | int rc, i; | 1031 | int rc, i; |
1028 | int copy_n; | 1032 | int copy_n; |
1033 | char msgbuf[80]; | ||
1029 | 1034 | ||
1030 | /* Stop buffer filling if there is no free track entries. | 1035 | /* Stop buffer filling if there is no free track entries. |
1031 | Don't fill up the last track entry (we wan't to store next track | 1036 | Don't fill up the last track entry (we wan't to store next track |
@@ -1087,10 +1092,28 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1087 | current_codec = last_codec; | 1092 | current_codec = last_codec; |
1088 | } | 1093 | } |
1089 | 1094 | ||
1095 | /* Get track metadata if we don't already have it. */ | ||
1096 | if (!tracks[track_widx].taginfo_ready) { | ||
1097 | if (!get_metadata(&tracks[track_widx],fd,trackname,v1first)) { | ||
1098 | logf("Metadata error!"); | ||
1099 | tracks[track_widx].filesize = 0; | ||
1100 | tracks[track_widx].filerem = 0; | ||
1101 | tracks[track_widx].taginfo_ready = false; | ||
1102 | close(fd); | ||
1103 | /* Skip invalid entry from playlist. */ | ||
1104 | playlist_skip_entry(NULL, peek_offset); | ||
1105 | goto peek_again; | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1090 | /* Load the codec. */ | 1109 | /* Load the codec. */ |
1091 | tracks[track_widx].codecbuf = &filebuf[buf_widx]; | 1110 | tracks[track_widx].codecbuf = &filebuf[buf_widx]; |
1092 | if (!loadcodec(trackname, start_play)) { | 1111 | if (!loadcodec(start_play)) { |
1112 | /* We should not use gui_syncplash from audio thread! */ | ||
1113 | snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname); | ||
1114 | gui_syncsplash(HZ*2, true, msgbuf); | ||
1093 | close(fd); | 1115 | close(fd); |
1116 | |||
1094 | /* Set filesize to zero to indicate no file was loaded. */ | 1117 | /* Set filesize to zero to indicate no file was loaded. */ |
1095 | tracks[track_widx].filesize = 0; | 1118 | tracks[track_widx].filesize = 0; |
1096 | tracks[track_widx].filerem = 0; | 1119 | tracks[track_widx].filerem = 0; |
@@ -1104,21 +1127,8 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1104 | } | 1127 | } |
1105 | return false; | 1128 | return false; |
1106 | } | 1129 | } |
1107 | // tracks[track_widx].filebuf = &filebuf[buf_widx]; | 1130 | |
1108 | tracks[track_widx].start_pos = 0; | 1131 | tracks[track_widx].start_pos = 0; |
1109 | |||
1110 | /* Get track metadata if we don't already have it. */ | ||
1111 | if (!tracks[track_widx].taginfo_ready) { | ||
1112 | if (!get_metadata(&tracks[track_widx],fd,trackname,v1first)) { | ||
1113 | logf("Metadata error!"); | ||
1114 | tracks[track_widx].filesize = 0; | ||
1115 | tracks[track_widx].filerem = 0; | ||
1116 | close(fd); | ||
1117 | /* Skip invalid entry from playlist. */ | ||
1118 | playlist_skip_entry(NULL, peek_offset); | ||
1119 | goto peek_again; | ||
1120 | } | ||
1121 | } | ||
1122 | set_filebuf_watermark(buffer_margin); | 1132 | set_filebuf_watermark(buffer_margin); |
1123 | tracks[track_widx].id3.elapsed = 0; | 1133 | tracks[track_widx].id3.elapsed = 0; |
1124 | 1134 | ||
@@ -1220,40 +1230,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
1220 | return true; | 1230 | return true; |
1221 | } | 1231 | } |
1222 | 1232 | ||
1223 | void audio_play_start(int offset) | 1233 | static void audio_clear_track_entries(bool buffered_only) |
1224 | { | ||
1225 | if (current_fd >= 0) { | ||
1226 | close(current_fd); | ||
1227 | current_fd = -1; | ||
1228 | } | ||
1229 | |||
1230 | memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK); | ||
1231 | sound_set_volume(global_settings.volume); | ||
1232 | track_count = 0; | ||
1233 | track_widx = 0; | ||
1234 | track_ridx = 0; | ||
1235 | buf_ridx = 0; | ||
1236 | buf_widx = 0; | ||
1237 | filebufused = 0; | ||
1238 | pcmbuf_set_boost_mode(true); | ||
1239 | |||
1240 | fill_bytesleft = filebuflen; | ||
1241 | filling = true; | ||
1242 | last_peek_offset = -1; | ||
1243 | |||
1244 | if (audio_load_track(offset, true, 0)) { | ||
1245 | if (track_buffer_callback) { | ||
1246 | cur_ti->event_sent = true; | ||
1247 | track_buffer_callback(&cur_ti->id3, true); | ||
1248 | } | ||
1249 | } else { | ||
1250 | logf("Failure"); | ||
1251 | } | ||
1252 | |||
1253 | pcmbuf_set_boost_mode(false); | ||
1254 | } | ||
1255 | |||
1256 | void audio_clear_track_entries(bool buffered_only) | ||
1257 | { | 1234 | { |
1258 | int cur_idx, event_count; | 1235 | int cur_idx, event_count; |
1259 | int i; | 1236 | int i; |
@@ -1290,6 +1267,61 @@ void audio_clear_track_entries(bool buffered_only) | |||
1290 | } | 1267 | } |
1291 | } | 1268 | } |
1292 | 1269 | ||
1270 | static void audio_stop_playback(bool resume) | ||
1271 | { | ||
1272 | paused = false; | ||
1273 | if (playing) | ||
1274 | playlist_update_resume_info(resume ? audio_current_track() : NULL); | ||
1275 | playing = false; | ||
1276 | filling = false; | ||
1277 | ci.stop_codec = true; | ||
1278 | if (current_fd >= 0) { | ||
1279 | close(current_fd); | ||
1280 | current_fd = -1; | ||
1281 | } | ||
1282 | pcmbuf_play_stop(); | ||
1283 | while (audio_codec_loaded) | ||
1284 | yield(); | ||
1285 | |||
1286 | track_count = 0; | ||
1287 | /* Mark all entries null. */ | ||
1288 | audio_clear_track_entries(false); | ||
1289 | } | ||
1290 | |||
1291 | static void audio_play_start(int offset) | ||
1292 | { | ||
1293 | if (current_fd >= 0) { | ||
1294 | close(current_fd); | ||
1295 | current_fd = -1; | ||
1296 | } | ||
1297 | |||
1298 | memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK); | ||
1299 | sound_set_volume(global_settings.volume); | ||
1300 | track_count = 0; | ||
1301 | track_widx = 0; | ||
1302 | track_ridx = 0; | ||
1303 | buf_ridx = 0; | ||
1304 | buf_widx = 0; | ||
1305 | filebufused = 0; | ||
1306 | pcmbuf_set_boost_mode(true); | ||
1307 | |||
1308 | fill_bytesleft = filebuflen; | ||
1309 | filling = true; | ||
1310 | last_peek_offset = -1; | ||
1311 | |||
1312 | if (audio_load_track(offset, true, 0)) { | ||
1313 | if (track_buffer_callback) { | ||
1314 | cur_ti->event_sent = true; | ||
1315 | track_buffer_callback(&cur_ti->id3, true); | ||
1316 | } | ||
1317 | } else { | ||
1318 | logf("Failure"); | ||
1319 | audio_stop_playback(false); | ||
1320 | } | ||
1321 | |||
1322 | pcmbuf_set_boost_mode(false); | ||
1323 | } | ||
1324 | |||
1293 | /* Send callback events to notify about new tracks. */ | 1325 | /* Send callback events to notify about new tracks. */ |
1294 | static void generate_postbuffer_events(void) | 1326 | static void generate_postbuffer_events(void) |
1295 | { | 1327 | { |
@@ -1322,7 +1354,7 @@ static void generate_postbuffer_events(void) | |||
1322 | } | 1354 | } |
1323 | } | 1355 | } |
1324 | 1356 | ||
1325 | void initialize_buffer_fill(void) | 1357 | static void initialize_buffer_fill(void) |
1326 | { | 1358 | { |
1327 | int cur_idx, i; | 1359 | int cur_idx, i; |
1328 | 1360 | ||
@@ -1362,7 +1394,7 @@ void initialize_buffer_fill(void) | |||
1362 | audio_clear_track_entries(true); | 1394 | audio_clear_track_entries(true); |
1363 | } | 1395 | } |
1364 | 1396 | ||
1365 | void audio_check_buffer(void) | 1397 | static void audio_check_buffer(void) |
1366 | { | 1398 | { |
1367 | /* Start buffer filling as necessary. */ | 1399 | /* Start buffer filling as necessary. */ |
1368 | if ((!conf_watermark || filebufused > conf_watermark | 1400 | if ((!conf_watermark || filebufused > conf_watermark |
@@ -1415,33 +1447,8 @@ void audio_check_buffer(void) | |||
1415 | } | 1447 | } |
1416 | } | 1448 | } |
1417 | 1449 | ||
1418 | void audio_update_trackinfo(void) | 1450 | static void audio_update_trackinfo(void) |
1419 | { | 1451 | { |
1420 | if (new_track >= 0) { | ||
1421 | buf_ridx += cur_ti->available; | ||
1422 | filebufused -= cur_ti->available; | ||
1423 | |||
1424 | cur_ti = &tracks[track_ridx]; | ||
1425 | buf_ridx += cur_ti->codecsize; | ||
1426 | filebufused -= cur_ti->codecsize; | ||
1427 | if (buf_ridx >= filebuflen) | ||
1428 | buf_ridx -= filebuflen; | ||
1429 | |||
1430 | if (!filling) | ||
1431 | pcmbuf_set_boost_mode(false); | ||
1432 | } else { | ||
1433 | buf_ridx -= ci.curpos + cur_ti->codecsize; | ||
1434 | filebufused += ci.curpos + cur_ti->codecsize; | ||
1435 | cur_ti->available = cur_ti->filesize - cur_ti->filerem; | ||
1436 | |||
1437 | cur_ti = &tracks[track_ridx]; | ||
1438 | buf_ridx -= cur_ti->filesize; | ||
1439 | filebufused += cur_ti->filesize; | ||
1440 | cur_ti->available = cur_ti->filesize; | ||
1441 | if (buf_ridx < 0) | ||
1442 | buf_ridx = filebuflen + buf_ridx; | ||
1443 | } | ||
1444 | |||
1445 | ci.filesize = cur_ti->filesize; | 1452 | ci.filesize = cur_ti->filesize; |
1446 | cur_ti->id3.elapsed = 0; | 1453 | cur_ti->id3.elapsed = 0; |
1447 | cur_ti->id3.offset = 0; | 1454 | cur_ti->id3.offset = 0; |
@@ -1461,42 +1468,90 @@ void audio_update_trackinfo(void) | |||
1461 | codec_track_changed(); | 1468 | codec_track_changed(); |
1462 | } | 1469 | } |
1463 | 1470 | ||
1464 | static void audio_stop_playback(bool resume) | 1471 | enum { |
1472 | SKIP_FAIL, | ||
1473 | SKIP_OK_DISK, | ||
1474 | SKIP_OK_RAM, | ||
1475 | }; | ||
1476 | |||
1477 | /* Should handle all situations. */ | ||
1478 | static int skip_next_track(void) | ||
1465 | { | 1479 | { |
1466 | paused = false; | 1480 | logf("skip next"); |
1467 | if (playing) | 1481 | /* Manual track skipping. */ |
1468 | playlist_update_resume_info(resume ? audio_current_track() : NULL); | 1482 | if (new_track > 0) |
1469 | playing = false; | 1483 | last_peek_offset--; |
1470 | filling = false; | 1484 | |
1471 | ci.stop_codec = true; | 1485 | /* Automatic track skipping. */ |
1472 | if (current_fd >= 0) { | 1486 | else |
1473 | close(current_fd); | 1487 | { |
1474 | current_fd = -1; | 1488 | if (!playlist_check(1)) { |
1489 | ci.reload_codec = false; | ||
1490 | return SKIP_FAIL; | ||
1491 | } | ||
1492 | last_peek_offset--; | ||
1493 | playlist_next(1); | ||
1475 | } | 1494 | } |
1476 | pcmbuf_play_stop(); | ||
1477 | while (audio_codec_loaded) | ||
1478 | yield(); | ||
1479 | 1495 | ||
1480 | track_count = 0; | ||
1481 | /* Mark all entries null. */ | ||
1482 | audio_clear_track_entries(false); | ||
1483 | } | ||
1484 | |||
1485 | static bool advance_next_track(void) | ||
1486 | { | ||
1487 | if (++track_ridx >= MAX_TRACK) | 1496 | if (++track_ridx >= MAX_TRACK) |
1488 | track_ridx = 0; | 1497 | track_ridx = 0; |
1489 | 1498 | ||
1490 | /* Wait for new track data (codectype 0 is invalid). When a correct | 1499 | /* Wait for new track data. */ |
1491 | codectype is set, we can assume that the filesize is correct. */ | 1500 | while (tracks[track_ridx].filesize == 0 && filling |
1492 | while (tracks[track_ridx].id3.codectype == 0 && filling | ||
1493 | && !ci.stop_codec) | 1501 | && !ci.stop_codec) |
1494 | yield(); | 1502 | yield(); |
1495 | 1503 | ||
1496 | if (tracks[track_ridx].filesize > 0) | 1504 | if (tracks[track_ridx].filesize <= 0) |
1497 | return true; | 1505 | { |
1506 | logf("Loading from disk..."); | ||
1507 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1508 | return SKIP_OK_DISK; | ||
1509 | } | ||
1510 | |||
1511 | buf_ridx += cur_ti->available; | ||
1512 | filebufused -= cur_ti->available; | ||
1513 | |||
1514 | cur_ti = &tracks[track_ridx]; | ||
1515 | buf_ridx += cur_ti->codecsize; | ||
1516 | filebufused -= cur_ti->codecsize; | ||
1517 | if (buf_ridx >= filebuflen) | ||
1518 | buf_ridx -= filebuflen; | ||
1519 | audio_update_trackinfo(); | ||
1520 | |||
1521 | if (!filling) | ||
1522 | pcmbuf_set_boost_mode(false); | ||
1523 | |||
1524 | return SKIP_OK_RAM; | ||
1525 | } | ||
1498 | 1526 | ||
1499 | return false; | 1527 | static int skip_previous_track(void) |
1528 | { | ||
1529 | logf("skip previous"); | ||
1530 | last_peek_offset++; | ||
1531 | if (--track_ridx < 0) | ||
1532 | track_ridx += MAX_TRACK; | ||
1533 | |||
1534 | if (tracks[track_ridx].filesize == 0 || | ||
1535 | filebufused+ci.curpos+tracks[track_ridx].filesize | ||
1536 | /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) { | ||
1537 | logf("Loading from disk..."); | ||
1538 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1539 | return SKIP_OK_DISK; | ||
1540 | } | ||
1541 | |||
1542 | buf_ridx -= ci.curpos + cur_ti->codecsize; | ||
1543 | filebufused += ci.curpos + cur_ti->codecsize; | ||
1544 | cur_ti->available = cur_ti->filesize - cur_ti->filerem; | ||
1545 | |||
1546 | cur_ti = &tracks[track_ridx]; | ||
1547 | buf_ridx -= cur_ti->filesize; | ||
1548 | filebufused += cur_ti->filesize; | ||
1549 | cur_ti->available = cur_ti->filesize; | ||
1550 | if (buf_ridx < 0) | ||
1551 | buf_ridx += filebuflen; | ||
1552 | audio_update_trackinfo(); | ||
1553 | |||
1554 | return SKIP_OK_RAM; | ||
1500 | } | 1555 | } |
1501 | 1556 | ||
1502 | /* Request the next track with new codec. */ | 1557 | /* Request the next track with new codec. */ |
@@ -1504,33 +1559,28 @@ static void audio_change_track(void) | |||
1504 | { | 1559 | { |
1505 | logf("change track"); | 1560 | logf("change track"); |
1506 | 1561 | ||
1507 | if (!advance_next_track()) | 1562 | if (!ci.reload_codec) |
1508 | { | 1563 | { |
1509 | logf("No more tracks"); | 1564 | if (skip_next_track() == SKIP_FAIL) |
1510 | while (pcm_is_playing()) | 1565 | { |
1566 | logf("No more tracks"); | ||
1567 | while (pcm_is_playing()) | ||
1511 | sleep(1); | 1568 | sleep(1); |
1512 | audio_stop_playback(false); | 1569 | audio_stop_playback(false); |
1513 | return ; | 1570 | return ; |
1571 | } | ||
1514 | } | 1572 | } |
1515 | 1573 | ||
1516 | audio_update_trackinfo(); | 1574 | ci.reload_codec = false; |
1517 | queue_post(&codec_queue, CODEC_LOAD, 0); | 1575 | /* Needed for fast skipping. */ |
1518 | } | 1576 | if (cur_ti->codecsize > 0) |
1519 | 1577 | queue_post(&codec_queue, CODEC_LOAD, 0); | |
1520 | static int get_codec_base_type(int type) | ||
1521 | { | ||
1522 | switch (type) { | ||
1523 | case AFMT_MPA_L1: | ||
1524 | case AFMT_MPA_L2: | ||
1525 | case AFMT_MPA_L3: | ||
1526 | return AFMT_MPA_L3; | ||
1527 | } | ||
1528 | |||
1529 | return type; | ||
1530 | } | 1578 | } |
1531 | 1579 | ||
1532 | bool codec_request_next_track_callback(void) | 1580 | bool codec_request_next_track_callback(void) |
1533 | { | 1581 | { |
1582 | struct track_info *prev_ti = cur_ti; | ||
1583 | |||
1534 | if (current_codec == CODEC_IDX_VOICE) { | 1584 | if (current_codec == CODEC_IDX_VOICE) { |
1535 | voice_remaining = 0; | 1585 | voice_remaining = 0; |
1536 | /* Terminate the codec if there are messages waiting on the queue or | 1586 | /* Terminate the codec if there are messages waiting on the queue or |
@@ -1544,67 +1594,40 @@ bool codec_request_next_track_callback(void) | |||
1544 | logf("Request new track"); | 1594 | logf("Request new track"); |
1545 | 1595 | ||
1546 | /* Advance to next track. */ | 1596 | /* Advance to next track. */ |
1547 | if (ci.reload_codec && new_track > 0) { | 1597 | if (new_track >= 0 || !ci.reload_codec) { |
1548 | last_peek_offset--; | 1598 | if (skip_next_track() != SKIP_OK_RAM) |
1549 | |||
1550 | if (!advance_next_track()) { | ||
1551 | logf("Loading from disk..."); | ||
1552 | new_track = 0; | ||
1553 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1554 | return false; | 1599 | return false; |
1555 | } | ||
1556 | } | 1600 | } |
1557 | 1601 | ||
1558 | /* Advance to previous track. */ | 1602 | /* Advance to previous track. */ |
1559 | else if (ci.reload_codec && new_track < 0) { | 1603 | else { |
1560 | last_peek_offset++; | 1604 | if (skip_previous_track() != SKIP_OK_RAM) |
1561 | if (--track_ridx < 0) | ||
1562 | track_ridx = MAX_TRACK-1; | ||
1563 | if (tracks[track_ridx].filesize == 0 || | ||
1564 | filebufused+ci.curpos+tracks[track_ridx].filesize | ||
1565 | /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) { | ||
1566 | logf("Loading from disk..."); | ||
1567 | new_track = 0; | ||
1568 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1569 | return false; | 1605 | return false; |
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | /* Codec requested track change (next track). */ | ||
1574 | else { | ||
1575 | if (!playlist_check(1)) { | ||
1576 | ci.reload_codec = false; | ||
1577 | return false; | ||
1578 | } | ||
1579 | last_peek_offset--; | ||
1580 | playlist_next(1); | ||
1581 | |||
1582 | if (!advance_next_track()) { | ||
1583 | logf("No more tracks [2]"); | ||
1584 | ci.stop_codec = true; | ||
1585 | new_track = 0; | ||
1586 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1587 | return false; | ||
1588 | } | ||
1589 | } | 1606 | } |
1590 | 1607 | ||
1608 | new_track = 0; | ||
1591 | ci.reload_codec = false; | 1609 | ci.reload_codec = false; |
1592 | 1610 | ||
1611 | logf("On-the-fly change"); | ||
1612 | |||
1593 | /* Check if the next codec is the same file. */ | 1613 | /* Check if the next codec is the same file. */ |
1594 | if (get_codec_base_type(cur_ti->id3.codectype) != | 1614 | if (get_codec_base_type(prev_ti->id3.codectype) != |
1595 | get_codec_base_type(tracks[track_ridx].id3.codectype)) { | 1615 | get_codec_base_type(cur_ti->id3.codectype)) |
1616 | { | ||
1596 | logf("New codec:%d/%d", cur_ti->id3.codectype, | 1617 | logf("New codec:%d/%d", cur_ti->id3.codectype, |
1597 | tracks[track_ridx].id3.codectype); | 1618 | tracks[track_ridx].id3.codectype); |
1598 | if (--track_ridx < 0) | 1619 | |
1599 | track_ridx = MAX_TRACK-1; | 1620 | if (cur_ti->codecsize == 0) |
1600 | new_track = 0; | 1621 | { |
1622 | logf("Loading from disk [2]..."); | ||
1623 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1624 | } | ||
1625 | else | ||
1626 | ci.reload_codec = true; | ||
1627 | |||
1601 | return false; | 1628 | return false; |
1602 | } | 1629 | } |
1603 | 1630 | ||
1604 | logf("On-the-fly change"); | ||
1605 | audio_update_trackinfo(); | ||
1606 | new_track = 0; | ||
1607 | |||
1608 | return true; | 1631 | return true; |
1609 | } | 1632 | } |
1610 | 1633 | ||
@@ -1632,8 +1655,8 @@ void audio_invalidate_tracks(void) | |||
1632 | 1655 | ||
1633 | static void initiate_track_change(int peek_index) | 1656 | static void initiate_track_change(int peek_index) |
1634 | { | 1657 | { |
1635 | /* Detect if disk is spinning.. */ | 1658 | /* Detect if disk is spinning or already loading. */ |
1636 | if (filling) { | 1659 | if (filling || ci.reload_codec || !audio_codec_loaded) { |
1637 | queue_post(&audio_queue, AUDIO_PLAY, 0); | 1660 | queue_post(&audio_queue, AUDIO_PLAY, 0); |
1638 | } else { | 1661 | } else { |
1639 | new_track = peek_index; | 1662 | new_track = peek_index; |
@@ -1808,6 +1831,8 @@ void codec_thread(void) | |||
1808 | while (1) { | 1831 | while (1) { |
1809 | status = 0; | 1832 | status = 0; |
1810 | queue_wait(&codec_queue, &ev); | 1833 | queue_wait(&codec_queue, &ev); |
1834 | new_track = 0; | ||
1835 | |||
1811 | switch (ev.id) { | 1836 | switch (ev.id) { |
1812 | case CODEC_LOAD_DISK: | 1837 | case CODEC_LOAD_DISK: |
1813 | ci.stop_codec = false; | 1838 | ci.stop_codec = false; |
@@ -1862,12 +1887,13 @@ void codec_thread(void) | |||
1862 | if (status != CODEC_OK) { | 1887 | if (status != CODEC_OK) { |
1863 | logf("Codec failure"); | 1888 | logf("Codec failure"); |
1864 | // audio_stop_playback(); | 1889 | // audio_stop_playback(); |
1890 | ci.reload_codec = false; | ||
1865 | gui_syncsplash(HZ*2, true, "Codec failure"); | 1891 | gui_syncsplash(HZ*2, true, "Codec failure"); |
1866 | } else { | 1892 | } else { |
1867 | logf("Codec finished"); | 1893 | logf("Codec finished"); |
1868 | } | 1894 | } |
1869 | 1895 | ||
1870 | if (playing && !ci.stop_codec && !ci.reload_codec) | 1896 | if (playing && !ci.stop_codec) |
1871 | audio_change_track(); | 1897 | audio_change_track(); |
1872 | 1898 | ||
1873 | // queue_post(&audio_queue, AUDIO_CODEC_DONE, (void *)status); | 1899 | // queue_post(&audio_queue, AUDIO_CODEC_DONE, (void *)status); |