summaryrefslogtreecommitdiff
path: root/firmware/mpeg.c
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-08-21 21:15:32 +0000
committerJens Arnold <amiconn@rockbox.org>2005-08-21 21:15:32 +0000
commitdece414749fa7155020e5794debfcb657e79fa66 (patch)
tree6a74e6272806e049c9763b3aa7ce01b55b3df5c2 /firmware/mpeg.c
parentc9caf9781befd2a40d4599ead126f3e6e480e739 (diff)
downloadrockbox-dece414749fa7155020e5794debfcb657e79fa66.tar.gz
rockbox-dece414749fa7155020e5794debfcb657e79fa66.zip
Hooked up the runtime database on archos.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7376 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r--firmware/mpeg.c125
1 files changed, 118 insertions, 7 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 0406376e00..575ba29fe3 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -84,6 +84,9 @@ extern int playlist_update_resume_info(const struct mp3entry* id3);
84#define MPEG_SAVE_DATA 102 84#define MPEG_SAVE_DATA 102
85#define MPEG_STOP_DONE 103 85#define MPEG_STOP_DONE 103
86 86
87/* indicator for MPEG_NEED_DATA */
88#define GENERATE_UNBUFFER_EVENTS ((void*)1)
89
87/* list of tracks in memory */ 90/* list of tracks in memory */
88#define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */ 91#define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */
89#define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1) 92#define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1)
@@ -93,6 +96,7 @@ struct trackdata
93 struct mp3entry id3; 96 struct mp3entry id3;
94 int mempos; 97 int mempos;
95 int load_ahead_index; 98 int load_ahead_index;
99 bool event_sent;
96}; 100};
97 101
98static struct trackdata trackdata[MAX_TRACK_ENTRIES]; 102static struct trackdata trackdata[MAX_TRACK_ENTRIES];
@@ -105,6 +109,11 @@ static int track_read_idx = 0;
105static int track_write_idx = 0; 109static int track_write_idx = 0;
106#endif /* !SIMULATOR */ 110#endif /* !SIMULATOR */
107 111
112/* Callback function to call when current track has really changed. */
113void (*track_changed_callback)(struct mp3entry *id3);
114void (*track_buffer_callback)(struct mp3entry *id3, bool last_track);
115void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track);
116
108static const char mpeg_thread_name[] = "mpeg"; 117static const char mpeg_thread_name[] = "mpeg";
109static unsigned int mpeg_errno; 118static unsigned int mpeg_errno;
110 119
@@ -400,8 +409,89 @@ unsigned long mpeg_get_last_header(void)
400#endif /* !SIMULATOR */ 409#endif /* !SIMULATOR */
401} 410}
402 411
412void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
413 bool last_track))
414{
415 track_buffer_callback = handler;
416}
417
418void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
419 bool last_track))
420{
421 track_unbuffer_callback = handler;
422}
423
424void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
425{
426 track_changed_callback = handler;
427}
403 428
404#ifndef SIMULATOR 429#ifndef SIMULATOR
430/* Send callback events to notify about removing old tracks. */
431static void generate_unbuffer_events(void)
432{
433 int i;
434 int event_count = 0;
435 int numentries = MAX_TRACK_ENTRIES - num_tracks_in_memory();
436 int cur_idx = track_write_idx;
437
438 for (i = 0; i < numentries; i++)
439 {
440 if (trackdata[cur_idx].event_sent)
441 event_count++;
442
443 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
444 }
445
446 cur_idx = track_write_idx;
447
448 for (i = 0; i < numentries; i++)
449 {
450 /* Send an event to notify that track has finished. */
451 if (trackdata[cur_idx].event_sent)
452 {
453 event_count--;
454 if (track_unbuffer_callback)
455 track_unbuffer_callback(&trackdata[cur_idx].id3,
456 event_count == 0);
457 trackdata[cur_idx].event_sent = false;
458 }
459 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
460 }
461}
462
463/* Send callback events to notify about new tracks. */
464static void generate_postbuffer_events(void)
465{
466 int i;
467 int event_count = 0;
468 int numentries = num_tracks_in_memory();
469 int cur_idx = track_read_idx;
470
471 for (i = 0; i < numentries; i++)
472 {
473 if (!trackdata[cur_idx].event_sent)
474 event_count++;
475
476 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
477 }
478
479 cur_idx = track_read_idx;
480
481 for (i = 0; i < numentries; i++)
482 {
483 if (!trackdata[cur_idx].event_sent)
484 {
485 event_count--;
486 if (track_buffer_callback)
487 track_buffer_callback(&trackdata[cur_idx].id3,
488 event_count == 0);
489 trackdata[cur_idx].event_sent = true;
490 }
491 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
492 }
493}
494
405static void recalculate_watermark(int bitrate) 495static void recalculate_watermark(int bitrate)
406{ 496{
407 int bytes_per_sec; 497 int bytes_per_sec;
@@ -684,7 +774,7 @@ static void transfer_end(unsigned char** ppbuf, int* psize)
684 if(!filling && unplayed_space_left < low_watermark) 774 if(!filling && unplayed_space_left < low_watermark)
685 { 775 {
686 filling = true; 776 filling = true;
687 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 777 queue_post(&mpeg_queue, MPEG_NEED_DATA, GENERATE_UNBUFFER_EVENTS);
688 } 778 }
689 779
690 if(unplayed_space_left) 780 if(unplayed_space_left)
@@ -862,6 +952,7 @@ static void stop_playing(void)
862 close(mpeg_file); 952 close(mpeg_file);
863 mpeg_file = -1; 953 mpeg_file = -1;
864 remove_all_tags(); 954 remove_all_tags();
955 generate_unbuffer_events();
865 reset_mp3_buffer(); 956 reset_mp3_buffer();
866} 957}
867 958
@@ -894,6 +985,8 @@ static void track_change(void)
894 if (num_tracks_in_memory() > 0) 985 if (num_tracks_in_memory() > 0)
895 { 986 {
896 remove_current_tag(); 987 remove_current_tag();
988 if (track_changed_callback)
989 track_changed_callback(audio_current_track());
897 update_playlist(); 990 update_playlist();
898 } 991 }
899 992
@@ -935,9 +1028,15 @@ static void start_playback_if_ready(void)
935 !filling || dma_underrun) 1028 !filling || dma_underrun)
936 { 1029 {
937 DEBUGF("P\n"); 1030 DEBUGF("P\n");
938 play_pending = false; 1031 if (play_pending) /* don't do this when recovering from DMA underrun */
1032 {
1033 generate_postbuffer_events(); /* signal first track as buffered */
1034 if (track_changed_callback)
1035 track_changed_callback(audio_current_track());
1036 play_pending = false;
1037 }
939 playing = true; 1038 playing = true;
940 1039
941 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); 1040 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
942 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); 1041 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
943 dma_underrun = false; 1042 dma_underrun = false;
@@ -1066,6 +1165,7 @@ static void mpeg_thread(void)
1066 1165
1067 reset_mp3_buffer(); 1166 reset_mp3_buffer();
1068 remove_all_tags(); 1167 remove_all_tags();
1168 generate_unbuffer_events();
1069 1169
1070 if(mpeg_file >= 0) 1170 if(mpeg_file >= 0)
1071 close(mpeg_file); 1171 close(mpeg_file);
@@ -1170,7 +1270,7 @@ static void mpeg_thread(void)
1170 /* should we start reading more data? */ 1270 /* should we start reading more data? */
1171 if(!filling && (unplayed_space_left < low_watermark)) { 1271 if(!filling && (unplayed_space_left < low_watermark)) {
1172 filling = true; 1272 filling = true;
1173 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1273 queue_post(&mpeg_queue, MPEG_NEED_DATA, GENERATE_UNBUFFER_EVENTS);
1174 play_pending = true; 1274 play_pending = true;
1175 } else if(unswapped_space_left && 1275 } else if(unswapped_space_left &&
1176 unswapped_space_left > unplayed_space_left) { 1276 unswapped_space_left > unplayed_space_left) {
@@ -1194,6 +1294,7 @@ static void mpeg_thread(void)
1194 1294
1195 reset_mp3_buffer(); 1295 reset_mp3_buffer();
1196 remove_all_tags(); 1296 remove_all_tags();
1297 generate_unbuffer_events();
1197 1298
1198 /* Open the next file */ 1299 /* Open the next file */
1199 if (mpeg_file >= 0) 1300 if (mpeg_file >= 0)
@@ -1233,6 +1334,7 @@ static void mpeg_thread(void)
1233 1334
1234 reset_mp3_buffer(); 1335 reset_mp3_buffer();
1235 remove_all_tags(); 1336 remove_all_tags();
1337 generate_unbuffer_events();
1236 1338
1237 /* Open the next file */ 1339 /* Open the next file */
1238 if (mpeg_file >= 0) 1340 if (mpeg_file >= 0)
@@ -1324,7 +1426,7 @@ static void mpeg_thread(void)
1324 { 1426 {
1325 /* We need to load more data before starting */ 1427 /* We need to load more data before starting */
1326 filling = true; 1428 filling = true;
1327 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0); 1429 queue_post(&mpeg_queue, MPEG_NEED_DATA, GENERATE_UNBUFFER_EVENTS);
1328 play_pending = true; 1430 play_pending = true;
1329 } 1431 }
1330 else 1432 else
@@ -1348,6 +1450,7 @@ static void mpeg_thread(void)
1348 /* We have to reload the current track */ 1450 /* We have to reload the current track */
1349 close(mpeg_file); 1451 close(mpeg_file);
1350 remove_all_non_current_tags(); 1452 remove_all_non_current_tags();
1453 generate_unbuffer_events();
1351 mpeg_file = -1; 1454 mpeg_file = -1;
1352 } 1455 }
1353 1456
@@ -1396,6 +1499,7 @@ static void mpeg_thread(void)
1396 1499
1397 close(mpeg_file); 1500 close(mpeg_file);
1398 remove_all_non_current_tags(); 1501 remove_all_non_current_tags();
1502 generate_unbuffer_events();
1399 mpeg_file = -1; 1503 mpeg_file = -1;
1400 reload_track = true; 1504 reload_track = true;
1401 } 1505 }
@@ -1407,8 +1511,8 @@ static void mpeg_thread(void)
1407 if(reload_track && new_file(1) >= 0) 1511 if(reload_track && new_file(1) >= 0)
1408 { 1512 {
1409 /* Tell ourselves that we want more data */ 1513 /* Tell ourselves that we want more data */
1410 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1411 filling = true; 1514 filling = true;
1515 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1412 } 1516 }
1413 1517
1414 break; 1518 break;
@@ -1425,12 +1529,16 @@ static void mpeg_thread(void)
1425 1529
1426 /* Make sure that we don't fill the entire buffer */ 1530 /* Make sure that we don't fill the entire buffer */
1427 free_space_left -= MPEG_HIGH_WATER; 1531 free_space_left -= MPEG_HIGH_WATER;
1532
1533 if (ev.data == GENERATE_UNBUFFER_EVENTS)
1534 generate_unbuffer_events();
1428 1535
1429 /* do we have any more buffer space to fill? */ 1536 /* do we have any more buffer space to fill? */
1430 if(free_space_left <= 0) 1537 if(free_space_left <= 0)
1431 { 1538 {
1432 DEBUGF("0\n"); 1539 DEBUGF("0\n");
1433 filling = false; 1540 filling = false;
1541 generate_postbuffer_events();
1434 ata_sleep(); 1542 ata_sleep();
1435 break; 1543 break;
1436 } 1544 }
@@ -1575,7 +1683,7 @@ static void mpeg_thread(void)
1575 if (playing) 1683 if (playing)
1576 playlist_update_resume_info(audio_current_track()); 1684 playlist_update_resume_info(audio_current_track());
1577 break; 1685 break;
1578 } 1686 }
1579#if CONFIG_HWCODEC == MAS3587F 1687#if CONFIG_HWCODEC == MAS3587F
1580 } 1688 }
1581 else 1689 else
@@ -2673,6 +2781,9 @@ static void mpeg_thread(void)
2673void audio_init(void) 2781void audio_init(void)
2674{ 2782{
2675 mpeg_errno = 0; 2783 mpeg_errno = 0;
2784 track_buffer_callback = NULL;
2785 track_unbuffer_callback = NULL;
2786 track_changed_callback = NULL;
2676 2787
2677#ifndef SIMULATOR 2788#ifndef SIMULATOR
2678 audiobuflen = audiobufend - audiobuf; 2789 audiobuflen = audiobufend - audiobuf;