summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/playback.c143
1 files changed, 110 insertions, 33 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 1593b586fa..fef65f1e7d 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -135,6 +135,7 @@ struct track_info {
135 volatile int available; 135 volatile int available;
136 bool taginfo_ready; 136 bool taginfo_ready;
137 int playlist_offset; 137 int playlist_offset;
138 int elapsed_start;
138}; 139};
139 140
140/* Track information (count in file buffer, read/write indexes for 141/* Track information (count in file buffer, read/write indexes for
@@ -144,9 +145,6 @@ static volatile int track_ridx;
144static volatile int track_widx; 145static volatile int track_widx;
145static bool track_changed; 146static bool track_changed;
146 147
147/* Playlist position to tell the next track. */
148static int last_offset;
149
150/* Partially loaded song's file handle to continue buffering later. */ 148/* Partially loaded song's file handle to continue buffering later. */
151static int current_fd; 149static int current_fd;
152 150
@@ -168,6 +166,9 @@ static int new_track;
168 166
169static bool v1first = false; 167static bool v1first = false;
170 168
169static void mp3_set_elapsed(struct mp3entry* id3);
170int mp3_get_file_pos(void);
171
171#ifdef SIMULATOR 172#ifdef SIMULATOR
172bool audiobuffer_insert_sim(char *buf, size_t length) 173bool audiobuffer_insert_sim(char *buf, size_t length)
173{ 174{
@@ -193,6 +194,7 @@ void codec_set_elapsed_callback(unsigned int value)
193#else 194#else
194 latency = 0; 195 latency = 0;
195#endif 196#endif
197 value += cur_ti->elapsed_start;
196 if (value < latency) { 198 if (value < latency) {
197 cur_ti->id3.elapsed = 0; 199 cur_ti->id3.elapsed = 0;
198 } else if (value - latency > cur_ti->id3.elapsed 200 } else if (value - latency > cur_ti->id3.elapsed
@@ -252,7 +254,6 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
252 } 254 }
253 255
254 while ((int)*realsize > cur_ti->available) { 256 while ((int)*realsize > cur_ti->available) {
255 // logf("Buffer wait: %d", cur_ti->available);
256 yield(); 257 yield();
257 if (ci.stop_codec) { 258 if (ci.stop_codec) {
258 return NULL; 259 return NULL;
@@ -273,15 +274,24 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
273 274
274void codec_advance_buffer_callback(size_t amount) 275void codec_advance_buffer_callback(size_t amount)
275{ 276{
276 if ((int)amount > cur_ti->available) 277 if ((int)amount > cur_ti->available + cur_ti->filerem)
277 amount = cur_ti->available; 278 amount = cur_ti->available + cur_ti->filerem;
278 279
279 cur_ti->available -= amount; 280 if ((int)amount > cur_ti->available) {
280 codecbufused -= amount; 281 codecbufused = 0;
281 buf_ridx += amount; 282 buf_ridx = buf_widx;
282 if (buf_ridx >= codecbuflen) 283 cur_ti->available = 0;
283 buf_ridx -= codecbuflen; 284 while ((int)amount < cur_ti->available)
285 yield();
286 } else {
287 cur_ti->available -= amount;
288 codecbufused -= amount;
289 buf_ridx += amount;
290 if (buf_ridx >= codecbuflen)
291 buf_ridx -= codecbuflen;
292 }
284 ci.curpos += amount; 293 ci.curpos += amount;
294 cur_ti->id3.offset = ci.curpos;
285} 295}
286 296
287void codec_advance_buffer_loc_callback(void *ptr) 297void codec_advance_buffer_loc_callback(void *ptr)
@@ -292,8 +302,6 @@ void codec_advance_buffer_loc_callback(void *ptr)
292 codec_advance_buffer_callback(amount); 302 codec_advance_buffer_callback(amount);
293} 303}
294 304
295int mp3_get_file_pos(void);
296
297off_t codec_mp3_get_filepos_callback(int newtime) 305off_t codec_mp3_get_filepos_callback(int newtime)
298{ 306{
299 off_t newpos; 307 off_t newpos;
@@ -361,6 +369,8 @@ int probe_file_format(const char *filename)
361 return AFMT_MPA_L1; 369 return AFMT_MPA_L1;
362 else if (!strcmp("mp2", suffix)) 370 else if (!strcmp("mp2", suffix))
363 return AFMT_MPA_L2; 371 return AFMT_MPA_L2;
372 else if (!strcmp("mpa", suffix))
373 return AFMT_MPA_L2;
364 else if (!strcmp("mp3", suffix)) 374 else if (!strcmp("mp3", suffix))
365 return AFMT_MPA_L3; 375 return AFMT_MPA_L3;
366 else if (!strcmp("ogg", suffix)) 376 else if (!strcmp("ogg", suffix))
@@ -465,8 +475,9 @@ bool loadcodec(const char *trackname, bool start_play)
465 logf("Codec: Vorbis"); 475 logf("Codec: Vorbis");
466 codec_path = CODEC_VORBIS; 476 codec_path = CODEC_VORBIS;
467 break; 477 break;
478 case AFMT_MPA_L2:
468 case AFMT_MPA_L3: 479 case AFMT_MPA_L3:
469 logf("Codec: MPA L3"); 480 logf("Codec: MPA L2/L3");
470 codec_path = CODEC_MPA_L3; 481 codec_path = CODEC_MPA_L3;
471 break; 482 break;
472 case AFMT_PCM_WAV: 483 case AFMT_PCM_WAV:
@@ -561,11 +572,12 @@ bool audio_load_track(int offset, bool start_play)
561 off_t size; 572 off_t size;
562 int rc, i; 573 int rc, i;
563 int copy_n; 574 int copy_n;
575 int last_offset = 0;
564 576
565 if (track_count >= MAX_TRACK) 577 if (track_count >= MAX_TRACK)
566 return false; 578 return false;
567 579
568 trackname = playlist_peek(offset); 580 trackname = playlist_peek(last_offset);
569 if (!trackname) { 581 if (!trackname) {
570 return false; 582 return false;
571 } 583 }
@@ -573,7 +585,7 @@ bool audio_load_track(int offset, bool start_play)
573 fd = open(trackname, O_RDONLY); 585 fd = open(trackname, O_RDONLY);
574 if (fd < 0) 586 if (fd < 0)
575 return false; 587 return false;
576 588
577 size = filesize(fd); 589 size = filesize(fd);
578 tracks[track_widx].filerem = size; 590 tracks[track_widx].filerem = size;
579 tracks[track_widx].filesize = size; 591 tracks[track_widx].filesize = size;
@@ -608,6 +620,17 @@ bool audio_load_track(int offset, bool start_play)
608 mp3info(&tracks[track_widx].id3, trackname, v1first); 620 mp3info(&tracks[track_widx].id3, trackname, v1first);
609 lseek(fd, 0, SEEK_SET); 621 lseek(fd, 0, SEEK_SET);
610 get_mp3file_info(fd, &tracks[track_widx].mp3data); 622 get_mp3file_info(fd, &tracks[track_widx].mp3data);
623 if (offset) {
624 lseek(fd, offset, SEEK_SET);
625 tracks[track_widx].id3.offset = offset;
626 mp3_set_elapsed(&tracks[track_widx].id3);
627 tracks[track_widx].elapsed_start = tracks[track_widx].id3.elapsed;
628 tracks[track_widx].filepos = offset;
629 tracks[track_widx].filerem = tracks[track_widx].filesize - offset;
630 ci.curpos = offset;
631 } else {
632 lseek(fd, 0, SEEK_SET);
633 }
611 logf("T:%s", tracks[track_widx].id3.title); 634 logf("T:%s", tracks[track_widx].id3.title);
612 logf("L:%d", tracks[track_widx].id3.length); 635 logf("L:%d", tracks[track_widx].id3.length);
613 logf("O:%d", tracks[track_widx].id3.first_frame_offset); 636 logf("O:%d", tracks[track_widx].id3.first_frame_offset);
@@ -616,11 +639,9 @@ bool audio_load_track(int offset, bool start_play)
616 break ; 639 break ;
617 } 640 }
618 641
619 playlist_next(0);
620 last_offset++; 642 last_offset++;
621 track_count++; 643 track_count++;
622 lseek(fd, 0, SEEK_SET); 644 i = tracks[track_widx].filepos;
623 i = 0;
624 while (i < size) { 645 while (i < size) {
625 /* Give codecs some processing time to prevent glitches. */ 646 /* Give codecs some processing time to prevent glitches. */
626 yield_codecs(); 647 yield_codecs();
@@ -671,12 +692,13 @@ bool audio_load_track(int offset, bool start_play)
671 return true; 692 return true;
672} 693}
673 694
674void audio_insert_tracks(bool start_playing) 695void audio_insert_tracks(int offset, bool start_playing)
675{ 696{
676 fill_bytesleft = codecbuflen - codecbufused; 697 fill_bytesleft = codecbuflen - codecbufused;
677 filling = true; 698 filling = true;
678 while (audio_load_track(last_offset, start_playing)) { 699 while (audio_load_track(offset, start_playing)) {
679 start_playing = false; 700 start_playing = false;
701 offset = 0;
680 } 702 }
681 filling = false; 703 filling = false;
682} 704}
@@ -695,8 +717,7 @@ void audio_play_start(int offset)
695#ifndef SIMULATOR 717#ifndef SIMULATOR
696 pcm_set_boost_mode(true); 718 pcm_set_boost_mode(true);
697#endif 719#endif
698 last_offset = offset; 720 audio_insert_tracks(offset, true);
699 audio_insert_tracks(true);
700#ifndef SIMULATOR 721#ifndef SIMULATOR
701 pcm_set_boost_mode(false); 722 pcm_set_boost_mode(false);
702 ata_sleep(); 723 ata_sleep();
@@ -748,7 +769,7 @@ void audio_check_buffer(void)
748 769
749 /* Load new files to fill the entire buffer. */ 770 /* Load new files to fill the entire buffer. */
750 if (tracks[track_widx].filerem == 0) 771 if (tracks[track_widx].filerem == 0)
751 audio_insert_tracks(false); 772 audio_insert_tracks(0, false);
752 773
753#ifndef SIMULATOR 774#ifndef SIMULATOR
754 pcm_set_boost_mode(false); 775 pcm_set_boost_mode(false);
@@ -813,35 +834,35 @@ bool codec_request_next_track_callback(void)
813 834
814 /* Advance to next track. */ 835 /* Advance to next track. */
815 if (ci.reload_codec && new_track > 0) { 836 if (ci.reload_codec && new_track > 0) {
837 playlist_next(1);
816 if (++track_ridx == MAX_TRACK) 838 if (++track_ridx == MAX_TRACK)
817 track_ridx = 0; 839 track_ridx = 0;
818 if (tracks[track_ridx].filesize == 0) { 840 if (tracks[track_ridx].filesize == 0) {
819 logf("Loading from disk..."); 841 logf("Loading from disk...");
820 new_track = 0; 842 new_track = 0;
821 queue_post(&audio_queue, AUDIO_PLAY, (void *)(last_offset)); 843 queue_post(&audio_queue, AUDIO_PLAY, 0);
822 return false; 844 return false;
823 } 845 }
824 } 846 }
825 847
826 /* Advance to previous track. */ 848 /* Advance to previous track. */
827 else if (ci.reload_codec && new_track < 0) { 849 else if (ci.reload_codec && new_track < 0) {
850 playlist_next(-1);
828 if (--track_ridx < 0) 851 if (--track_ridx < 0)
829 track_ridx = MAX_TRACK-1; 852 track_ridx = MAX_TRACK-1;
830 if (tracks[track_ridx].filesize == 0 || 853 if (tracks[track_ridx].filesize == 0 ||
831 codecbufused+ci.curpos+tracks[track_ridx].filesize 854 codecbufused+ci.curpos+tracks[track_ridx].filesize
832 /*+ (off_t)tracks[track_ridx].codecsize*/ > codecbuflen) { 855 /*+ (off_t)tracks[track_ridx].codecsize*/ > codecbuflen) {
833 logf("Loading from disk..."); 856 logf("Loading from disk...");
834 last_offset -= track_count;
835 if (last_offset < 0)
836 last_offset = 0;
837 new_track = 0; 857 new_track = 0;
838 queue_post(&audio_queue, AUDIO_PLAY, (void *)(last_offset)); 858 queue_post(&audio_queue, AUDIO_PLAY, 0);
839 return false; 859 return false;
840 } 860 }
841 } 861 }
842 862
843 /* Codec requested track change (next track). */ 863 /* Codec requested track change (next track). */
844 else { 864 else {
865 playlist_next(1);
845 if (++track_ridx >= MAX_TRACK) 866 if (++track_ridx >= MAX_TRACK)
846 track_ridx = 0; 867 track_ridx = 0;
847 868
@@ -1085,9 +1106,10 @@ void audio_next(void)
1085 1106
1086 /* Detect if disk is spinning.. */ 1107 /* Detect if disk is spinning.. */
1087 if (filling) { 1108 if (filling) {
1109 playlist_next(1);
1088 playing = false; 1110 playing = false;
1089 ci.stop_codec = true; 1111 ci.stop_codec = true;
1090 queue_post(&audio_queue, AUDIO_PLAY, (void *)(last_offset)); 1112 queue_post(&audio_queue, AUDIO_PLAY, 0);
1091 } 1113 }
1092} 1114}
1093 1115
@@ -1101,11 +1123,10 @@ void audio_prev(void)
1101#endif 1123#endif
1102 1124
1103 if (filling) { 1125 if (filling) {
1126 playlist_next(-1);
1104 playing = false; 1127 playing = false;
1105 ci.stop_codec = true; 1128 ci.stop_codec = true;
1106 if (--last_offset < 0) 1129 queue_post(&audio_queue, AUDIO_PLAY, 0);
1107 last_offset = 0;
1108 queue_post(&audio_queue, AUDIO_PLAY, (void *)(last_offset));
1109 } 1130 }
1110 //queue_post(&audio_queue, AUDIO_PREV, 0); 1131 //queue_post(&audio_queue, AUDIO_PREV, 0);
1111} 1132}
@@ -1147,6 +1168,62 @@ int audio_get_file_pos(void)
1147 1168
1148 1169
1149/* Copied from mpeg.c. Should be moved somewhere else. */ 1170/* Copied from mpeg.c. Should be moved somewhere else. */
1171static void mp3_set_elapsed(struct mp3entry* id3)
1172{
1173 if ( id3->vbr ) {
1174 if ( id3->has_toc ) {
1175 /* calculate elapsed time using TOC */
1176 int i;
1177 unsigned int remainder, plen, relpos, nextpos;
1178
1179 /* find wich percent we're at */
1180 for (i=0; i<100; i++ )
1181 {
1182 if ( id3->offset < (int)(id3->toc[i] * (id3->filesize / 256)) )
1183 {
1184 break;
1185 }
1186 }
1187
1188 i--;
1189 if (i < 0)
1190 i = 0;
1191
1192 relpos = id3->toc[i];
1193
1194 if (i < 99)
1195 {
1196 nextpos = id3->toc[i+1];
1197 }
1198 else
1199 {
1200 nextpos = 256;
1201 }
1202
1203 remainder = id3->offset - (relpos * (id3->filesize / 256));
1204
1205 /* set time for this percent (divide before multiply to prevent
1206 overflow on long files. loss of precision is negligible on
1207 short files) */
1208 id3->elapsed = i * (id3->length / 100);
1209
1210 /* calculate remainder time */
1211 plen = (nextpos - relpos) * (id3->filesize / 256);
1212 id3->elapsed += (((remainder * 100) / plen) *
1213 (id3->length / 10000));
1214 }
1215 else {
1216 /* no TOC exists. set a rough estimate using average bitrate */
1217 int tpk = id3->length / (id3->filesize / 1024);
1218 id3->elapsed = id3->offset / 1024 * tpk;
1219 }
1220 }
1221 else
1222 /* constant bitrate == simple frame calculation */
1223 id3->elapsed = id3->offset / id3->bpf * id3->tpf;
1224}
1225
1226/* Copied from mpeg.c. Should be moved somewhere else. */
1150int mp3_get_file_pos(void) 1227int mp3_get_file_pos(void)
1151{ 1228{
1152 int pos = -1; 1229 int pos = -1;