summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c333
1 files changed, 230 insertions, 103 deletions
diff --git a/apps/playback.c b/apps/playback.c
index b20603f1c9..16e1e1c24c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -177,6 +177,7 @@ struct voice_info {
177 177
178 178
179static struct mutex mutex_codecthread; 179static struct mutex mutex_codecthread;
180static struct mutex mutex_buffering;
180static struct event_queue codec_callback_queue; 181static struct event_queue codec_callback_queue;
181 182
182static struct mp3entry id3_voice; 183static struct mp3entry id3_voice;
@@ -333,18 +334,22 @@ static bool voice_pcmbuf_insert_split_callback(
333 while (length) 334 while (length)
334 { 335 {
335 long est_output_size = dsp_output_size(length); 336 long est_output_size = dsp_output_size(length);
337
336 while ((dest = pcmbuf_request_voice_buffer(est_output_size, 338 while ((dest = pcmbuf_request_voice_buffer(est_output_size,
337 &output_size, playing)) == NULL) 339 &output_size, playing)) == NULL)
340 {
338 if (playing) 341 if (playing)
339 swap_codec(); 342 swap_codec();
340 else 343 else
341 yield(); 344 yield();
342 345 }
346
343 /* Get the real input_size for output_size bytes, guarding 347 /* Get the real input_size for output_size bytes, guarding
344 * against resampling buffer overflows. */ 348 * against resampling buffer overflows. */
345 input_size = dsp_input_size(output_size); 349 input_size = dsp_input_size(output_size);
346 350
347 if (input_size <= 0) { 351 if (input_size <= 0)
352 {
348 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n", 353 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
349 output_size, length, input_size); 354 output_size, length, input_size);
350 /* If this happens, there are samples of codec data that don't 355 /* If this happens, there are samples of codec data that don't
@@ -395,7 +400,8 @@ static bool codec_pcmbuf_insert_split_callback(
395 return true; 400 return true;
396 401
397 while ((dest = pcmbuf_request_buffer(est_output_size, 402 while ((dest = pcmbuf_request_buffer(est_output_size,
398 &output_size)) == NULL) { 403 &output_size)) == NULL)
404 {
399 sleep(1); 405 sleep(1);
400 if (ci.seek_time || ci.new_track || ci.stop_codec) 406 if (ci.seek_time || ci.new_track || ci.stop_codec)
401 return true; 407 return true;
@@ -405,7 +411,8 @@ static bool codec_pcmbuf_insert_split_callback(
405 * against resampling buffer overflows. */ 411 * against resampling buffer overflows. */
406 input_size = dsp_input_size(output_size); 412 input_size = dsp_input_size(output_size);
407 413
408 if (input_size <= 0) { 414 if (input_size <= 0)
415 {
409 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n", 416 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
410 output_size, length, input_size); 417 output_size, length, input_size);
411 /* If this happens, there are samples of codec data that don't 418 /* If this happens, there are samples of codec data that don't
@@ -423,8 +430,10 @@ static bool codec_pcmbuf_insert_split_callback(
423 430
424 if (voice_is_playing && pcm_is_playing() && 431 if (voice_is_playing && pcm_is_playing() &&
425 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80) 432 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
433 {
426 swap_codec(); 434 swap_codec();
427 435 }
436
428 length -= input_size; 437 length -= input_size;
429 } 438 }
430 439
@@ -475,15 +484,18 @@ static void* get_codec_memory_callback(size_t *size)
475} 484}
476 485
477static void pcmbuf_position_callback(size_t size) ICODE_ATTR; 486static void pcmbuf_position_callback(size_t size) ICODE_ATTR;
478static void pcmbuf_position_callback(size_t size) { 487static void pcmbuf_position_callback(size_t size)
488{
479 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY + 489 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
480 prev_ti->id3.elapsed; 490 prev_ti->id3.elapsed;
481 if (time >= prev_ti->id3.length) { 491
492 if (time >= prev_ti->id3.length)
493 {
482 pcmbuf_set_position_callback(NULL); 494 pcmbuf_set_position_callback(NULL);
483 prev_ti->id3.elapsed = prev_ti->id3.length; 495 prev_ti->id3.elapsed = prev_ti->id3.length;
484 } else { 496 }
497 else
485 prev_ti->id3.elapsed = time; 498 prev_ti->id3.elapsed = time;
486 }
487} 499}
488 500
489static void voice_set_elapsed_callback(unsigned int value) 501static void voice_set_elapsed_callback(unsigned int value)
@@ -506,7 +518,9 @@ static void codec_set_elapsed_callback(unsigned int value)
506 cur_ti->id3.elapsed = 0; 518 cur_ti->id3.elapsed = 0;
507 else if (value - latency > cur_ti->id3.elapsed || 519 else if (value - latency > cur_ti->id3.elapsed ||
508 value - latency < cur_ti->id3.elapsed - 2) 520 value - latency < cur_ti->id3.elapsed - 2)
521 {
509 cur_ti->id3.elapsed = value - latency; 522 cur_ti->id3.elapsed = value - latency;
523 }
510} 524}
511 525
512static void voice_set_offset_callback(size_t value) 526static void voice_set_offset_callback(size_t value)
@@ -517,6 +531,7 @@ static void voice_set_offset_callback(size_t value)
517static void codec_set_offset_callback(size_t value) 531static void codec_set_offset_callback(size_t value)
518{ 532{
519 unsigned int latency; 533 unsigned int latency;
534
520 if (ci.seek_time) 535 if (ci.seek_time)
521 return; 536 return;
522 537
@@ -543,8 +558,8 @@ static bool have_free_tracks(void)
543 return track_widx + 1 < track_ridx; 558 return track_widx + 1 < track_ridx;
544 else if (track_ridx == 0) 559 else if (track_ridx == 0)
545 return track_widx < MAX_TRACK - 1; 560 return track_widx < MAX_TRACK - 1;
546 else 561
547 return true; 562 return true;
548} 563}
549 564
550int audio_track_count(void) 565int audio_track_count(void)
@@ -552,25 +567,33 @@ int audio_track_count(void)
552 if (have_tracks()) 567 if (have_tracks())
553 { 568 {
554 int relative_track_widx = track_widx; 569 int relative_track_widx = track_widx;
570
555 if (track_ridx > track_widx) 571 if (track_ridx > track_widx)
556 relative_track_widx += MAX_TRACK; 572 relative_track_widx += MAX_TRACK;
573
557 return relative_track_widx - track_ridx + 1; 574 return relative_track_widx - track_ridx + 1;
558 } else 575 }
559 return 0; 576
577 return 0;
560} 578}
561 579
562static void advance_buffer_counters(size_t amount) { 580static void advance_buffer_counters(size_t amount)
581{
563 buf_ridx += amount; 582 buf_ridx += amount;
583
564 if (buf_ridx >= filebuflen) 584 if (buf_ridx >= filebuflen)
565 buf_ridx -= filebuflen; 585 buf_ridx -= filebuflen;
586
566 ci.curpos += amount; 587 ci.curpos += amount;
567 cur_ti->available -= amount; 588 cur_ti->available -= amount;
568 filebufused -= amount; 589 filebufused -= amount;
569 590
570 /* Start buffer filling as necessary. */ 591 /* Start buffer filling as necessary. */
571 if (!pcmbuf_is_lowdata() && !filling) 592 if (!pcmbuf_is_lowdata() && !filling)
593 {
572 if (conf_watermark && filebufused <= conf_watermark && playing) 594 if (conf_watermark && filebufused <= conf_watermark && playing)
573 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); 595 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
596 }
574} 597}
575 598
576static size_t voice_filebuf_callback(void *ptr, size_t size) 599static size_t voice_filebuf_callback(void *ptr, size_t size)
@@ -600,9 +623,11 @@ static size_t codec_filebuf_callback(void *ptr, size_t size)
600 return 0; 623 return 0;
601 624
602 /* Let the disk buffer catch fill until enough data is available */ 625 /* Let the disk buffer catch fill until enough data is available */
603 while (copy_n > cur_ti->available) { 626 while (copy_n > cur_ti->available)
627 {
604 if (!filling) 628 if (!filling)
605 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); 629 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
630
606 sleep(1); 631 sleep(1);
607 if (ci.stop_codec || ci.new_track) 632 if (ci.stop_codec || ci.new_track)
608 return 0; 633 return 0;
@@ -721,22 +746,27 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
721{ 746{
722 size_t short_n, copy_n, buf_rem; 747 size_t short_n, copy_n, buf_rem;
723 748
724 if (!playing) { 749 if (!playing)
750 {
725 *realsize = 0; 751 *realsize = 0;
726 return NULL; 752 return NULL;
727 } 753 }
728 754
729 copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem); 755 copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem);
730 if (copy_n == 0) { 756 if (copy_n == 0)
757 {
731 *realsize = 0; 758 *realsize = 0;
732 return NULL; 759 return NULL;
733 } 760 }
734 761
735 while (copy_n > cur_ti->available) { 762 while (copy_n > cur_ti->available)
763 {
736 if (!filling) 764 if (!filling)
737 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); 765 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
766
738 sleep(1); 767 sleep(1);
739 if (ci.stop_codec || ci.new_track) { 768 if (ci.stop_codec || ci.new_track)
769 {
740 *realsize = 0; 770 *realsize = 0;
741 return NULL; 771 return NULL;
742 } 772 }
@@ -744,10 +774,13 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
744 774
745 /* How much is left at the end of the file buffer before wrap? */ 775 /* How much is left at the end of the file buffer before wrap? */
746 buf_rem = filebuflen - buf_ridx; 776 buf_rem = filebuflen - buf_ridx;
777
747 /* If we can't satisfy the request without wrapping */ 778 /* If we can't satisfy the request without wrapping */
748 if (buf_rem < copy_n) { 779 if (buf_rem < copy_n)
780 {
749 /* How short are we? */ 781 /* How short are we? */
750 short_n = copy_n - buf_rem; 782 short_n = copy_n - buf_rem;
783
751 /* If we can fudge it with the guardbuf */ 784 /* If we can fudge it with the guardbuf */
752 if (short_n < GUARD_BUFSIZE) 785 if (short_n < GUARD_BUFSIZE)
753 memcpy(&filebuf[filebuflen], &filebuf[0], short_n); 786 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
@@ -756,6 +789,7 @@ static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
756 } 789 }
757 790
758 *realsize = copy_n; 791 *realsize = copy_n;
792
759 return (char *)&filebuf[buf_ridx]; 793 return (char *)&filebuf[buf_ridx];
760} 794}
761 795
@@ -772,7 +806,8 @@ static int get_codec_base_type(int type)
772} 806}
773 807
774/* Count the data BETWEEN the selected tracks */ 808/* Count the data BETWEEN the selected tracks */
775static size_t buffer_count_tracks(int from_track, int to_track) { 809static size_t buffer_count_tracks(int from_track, int to_track)
810{
776 size_t amount = 0; 811 size_t amount = 0;
777 bool need_wrap = to_track < from_track; 812 bool need_wrap = to_track < from_track;
778 813
@@ -783,8 +818,10 @@ static size_t buffer_count_tracks(int from_track, int to_track) {
783 from_track -= MAX_TRACK; 818 from_track -= MAX_TRACK;
784 need_wrap = false; 819 need_wrap = false;
785 } 820 }
821
786 if (from_track >= to_track && !need_wrap) 822 if (from_track >= to_track && !need_wrap)
787 break; 823 break;
824
788 amount += tracks[from_track].codecsize + tracks[from_track].filesize; 825 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
789 } 826 }
790 return amount; 827 return amount;
@@ -794,10 +831,14 @@ static bool buffer_wind_forward(int new_track_ridx, int old_track_ridx)
794{ 831{
795 size_t amount; 832 size_t amount;
796 833
834 mutex_lock(&mutex_buffering);
835
797 /* Start with the remainder of the previously playing track */ 836 /* Start with the remainder of the previously playing track */
798 amount = tracks[old_track_ridx].filesize - ci.curpos; 837 amount = tracks[old_track_ridx].filesize - ci.curpos;
799 /* Then collect all data from tracks in between them */ 838 /* Then collect all data from tracks in between them */
800 amount += buffer_count_tracks(old_track_ridx, new_track_ridx); 839 amount += buffer_count_tracks(old_track_ridx, new_track_ridx);
840
841 mutex_unlock(&mutex_buffering);
801 842
802 if (amount > filebufused) 843 if (amount > filebufused)
803 return false; 844 return false;
@@ -807,6 +848,7 @@ static bool buffer_wind_forward(int new_track_ridx, int old_track_ridx)
807 /* Wind the buffer to the beginning of the target track or its codec */ 848 /* Wind the buffer to the beginning of the target track or its codec */
808 buf_ridx += amount; 849 buf_ridx += amount;
809 filebufused -= amount; 850 filebufused -= amount;
851
810 /* Check and handle buffer wrapping */ 852 /* Check and handle buffer wrapping */
811 if (buf_ridx >= filebuflen) 853 if (buf_ridx >= filebuflen)
812 buf_ridx -= filebuflen; 854 buf_ridx -= filebuflen;
@@ -814,15 +856,21 @@ static bool buffer_wind_forward(int new_track_ridx, int old_track_ridx)
814 return true; 856 return true;
815} 857}
816 858
817static bool buffer_wind_backward(int new_track_ridx, int old_track_ridx) { 859static bool buffer_wind_backward(int new_track_ridx, int old_track_ridx)
860{
818 /* Available buffer data */ 861 /* Available buffer data */
819 size_t buf_back = buf_ridx; 862 size_t buf_back;
863 /* Start with the previously playing track's data and our data */
864 size_t amount;
865
866 mutex_lock(&mutex_buffering);
867
868 buf_back = buf_ridx;
869 amount = ci.curpos;
820 if (buf_ridx < buf_widx) 870 if (buf_ridx < buf_widx)
821 buf_back += filebuflen; 871 buf_back += filebuflen;
822 buf_back -= buf_widx; 872 buf_back -= buf_widx;
823 /* Start with the previously playing track's data and our data */ 873
824 size_t amount = ci.curpos;
825
826 /* If we're not just resetting the current track */ 874 /* If we're not just resetting the current track */
827 if (new_track_ridx != old_track_ridx) 875 if (new_track_ridx != old_track_ridx)
828 { 876 {
@@ -848,7 +896,10 @@ static bool buffer_wind_backward(int new_track_ridx, int old_track_ridx) {
848 896
849 /* Do we have space to make this skip? */ 897 /* Do we have space to make this skip? */
850 if (amount > buf_back) 898 if (amount > buf_back)
899 {
900 mutex_unlock(&mutex_buffering);
851 return false; 901 return false;
902 }
852 903
853 logf("bwb:%ldB",amount); 904 logf("bwb:%ldB",amount);
854 905
@@ -861,6 +912,7 @@ static bool buffer_wind_backward(int new_track_ridx, int old_track_ridx) {
861 912
862 /* Reset to the beginning of the new track */ 913 /* Reset to the beginning of the new track */
863 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize; 914 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
915 mutex_unlock(&mutex_buffering);
864 916
865 return true; 917 return true;
866} 918}
@@ -878,9 +930,11 @@ static void audio_update_trackinfo(void)
878static void audio_rebuffer(void) 930static void audio_rebuffer(void)
879{ 931{
880 logf("Forcing rebuffer"); 932 logf("Forcing rebuffer");
933
881 /* Notify the codec that this will take a while */ 934 /* Notify the codec that this will take a while */
882 if (!filling) 935 if (!filling)
883 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0); 936 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0);
937
884 /* Stop in progress fill, and clear open file descriptor */ 938 /* Stop in progress fill, and clear open file descriptor */
885 close(current_fd); 939 close(current_fd);
886 current_fd = -1; 940 current_fd = -1;
@@ -888,7 +942,7 @@ static void audio_rebuffer(void)
888 942
889 /* Reset buffer and track pointers */ 943 /* Reset buffer and track pointers */
890 buf_ridx = buf_widx = 0; 944 buf_ridx = buf_widx = 0;
891 track_widx = track_ridx; 945 track_widx = track_ridx = 0;
892 audio_clear_track_entries(false, true); 946 audio_clear_track_entries(false, true);
893 filebufused = 0; 947 filebufused = 0;
894 948
@@ -960,11 +1014,8 @@ static void audio_check_new_track(void)
960 new_playlist = false; 1014 new_playlist = false;
961 } 1015 }
962 1016
963 track_ridx+=ci.new_track; 1017 track_ridx += ci.new_track;
964 if (track_ridx >= MAX_TRACK) 1018 track_ridx &= MAX_TRACK_MASK;
965 track_ridx -= MAX_TRACK;
966 else if (track_ridx < 0)
967 track_ridx += MAX_TRACK;
968 1019
969 /* Save the old track */ 1020 /* Save the old track */
970 prev_ti = cur_ti; 1021 prev_ti = cur_ti;
@@ -1006,9 +1057,11 @@ static void audio_check_new_track(void)
1006 int cur_idx = track_ridx; 1057 int cur_idx = track_ridx;
1007 bool taginfo_ready = true; 1058 bool taginfo_ready = true;
1008 bool wrap = track_ridx > old_track_ridx; 1059 bool wrap = track_ridx > old_track_ridx;
1009 while (1) { 1060
1010 if (++cur_idx >= MAX_TRACK) 1061 while (1)
1011 cur_idx -= MAX_TRACK; 1062 {
1063 cur_idx++;
1064 cur_idx &= MAX_TRACK_MASK;
1012 if (!(wrap || cur_idx < old_track_ridx)) 1065 if (!(wrap || cur_idx < old_track_ridx))
1013 break; 1066 break;
1014 1067
@@ -1049,11 +1102,13 @@ static void rebuffer_and_seek(size_t newpos)
1049 /* (Re-)open current track's file handle. */ 1102 /* (Re-)open current track's file handle. */
1050 1103
1051 fd = open(trackname, O_RDONLY); 1104 fd = open(trackname, O_RDONLY);
1052 if (fd < 0) { 1105 if (fd < 0)
1106 {
1053 logf("Open failed!"); 1107 logf("Open failed!");
1054 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0); 1108 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
1055 return; 1109 return;
1056 } 1110 }
1111
1057 if (current_fd >= 0) 1112 if (current_fd >= 0)
1058 close(current_fd); 1113 close(current_fd);
1059 current_fd = fd; 1114 current_fd = fd;
@@ -1075,10 +1130,13 @@ static void rebuffer_and_seek(size_t newpos)
1075 last_peek_offset = 0; 1130 last_peek_offset = 0;
1076 initialize_buffer_fill(true); 1131 initialize_buffer_fill(true);
1077 1132
1078 if (newpos > AUDIO_REBUFFER_GUESS_SIZE) { 1133 if (newpos > AUDIO_REBUFFER_GUESS_SIZE)
1134 {
1079 buf_ridx += AUDIO_REBUFFER_GUESS_SIZE; 1135 buf_ridx += AUDIO_REBUFFER_GUESS_SIZE;
1080 cur_ti->start_pos = newpos - AUDIO_REBUFFER_GUESS_SIZE; 1136 cur_ti->start_pos = newpos - AUDIO_REBUFFER_GUESS_SIZE;
1081 } else { 1137 }
1138 else
1139 {
1082 buf_ridx += newpos; 1140 buf_ridx += newpos;
1083 cur_ti->start_pos = 0; 1141 cur_ti->start_pos = 0;
1084 } 1142 }
@@ -1106,10 +1164,13 @@ static void codec_advance_buffer_callback(size_t amount)
1106 while (amount > cur_ti->available && filling) 1164 while (amount > cur_ti->available && filling)
1107 sleep(1); 1165 sleep(1);
1108 1166
1109 if (amount > cur_ti->available) { 1167 if (amount > cur_ti->available)
1168 {
1110 struct event ev; 1169 struct event ev;
1170
1111 queue_post(&audio_queue, 1171 queue_post(&audio_queue,
1112 Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount)); 1172 Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount));
1173
1113 queue_wait(&codec_callback_queue, &ev); 1174 queue_wait(&codec_callback_queue, &ev);
1114 switch (ev.id) 1175 switch (ev.id)
1115 { 1176 {
@@ -1117,6 +1178,7 @@ static void codec_advance_buffer_callback(size_t amount)
1117 ci.stop_codec = true; 1178 ci.stop_codec = true;
1118 case Q_CODEC_REQUEST_COMPLETE: 1179 case Q_CODEC_REQUEST_COMPLETE:
1119 return; 1180 return;
1181
1120 default: 1182 default:
1121 logf("Bad event on ccq"); 1183 logf("Bad event on ccq");
1122 ci.stop_codec = true; 1184 ci.stop_codec = true;
@@ -1132,18 +1194,21 @@ static void codec_advance_buffer_callback(size_t amount)
1132static void voice_advance_buffer_loc_callback(void *ptr) 1194static void voice_advance_buffer_loc_callback(void *ptr)
1133{ 1195{
1134 size_t amount = (size_t)ptr - (size_t)voicebuf; 1196 size_t amount = (size_t)ptr - (size_t)voicebuf;
1197
1135 voice_advance_buffer_callback(amount); 1198 voice_advance_buffer_callback(amount);
1136} 1199}
1137 1200
1138static void codec_advance_buffer_loc_callback(void *ptr) 1201static void codec_advance_buffer_loc_callback(void *ptr)
1139{ 1202{
1140 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx]; 1203 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1204
1141 codec_advance_buffer_callback(amount); 1205 codec_advance_buffer_callback(amount);
1142} 1206}
1143 1207
1144static off_t voice_mp3_get_filepos_callback(int newtime) 1208static off_t voice_mp3_get_filepos_callback(int newtime)
1145{ 1209{
1146 (void)newtime; 1210 (void)newtime;
1211
1147 return 0; 1212 return 0;
1148} 1213}
1149 1214
@@ -1165,9 +1230,11 @@ static void voice_do_nothing(void)
1165static void codec_seek_complete_callback(void) 1230static void codec_seek_complete_callback(void)
1166{ 1231{
1167 logf("seek_complete"); 1232 logf("seek_complete");
1168 if (pcm_is_paused()) { 1233 if (pcm_is_paused())
1234 {
1169 /* If this is not a seamless seek, clear the buffer */ 1235 /* If this is not a seamless seek, clear the buffer */
1170 pcmbuf_play_stop(); 1236 pcmbuf_play_stop();
1237
1171 /* If playback was not 'deliberately' paused, unpause now */ 1238 /* If playback was not 'deliberately' paused, unpause now */
1172 if (!paused) 1239 if (!paused)
1173 pcmbuf_pause(false); 1240 pcmbuf_pause(false);
@@ -1178,6 +1245,7 @@ static void codec_seek_complete_callback(void)
1178static bool voice_seek_buffer_callback(size_t newpos) 1245static bool voice_seek_buffer_callback(size_t newpos)
1179{ 1246{
1180 (void)newpos; 1247 (void)newpos;
1248
1181 return false; 1249 return false;
1182} 1250}
1183 1251
@@ -1189,7 +1257,8 @@ static bool codec_seek_buffer_callback(size_t newpos)
1189 newpos = cur_ti->filesize - 1; 1257 newpos = cur_ti->filesize - 1;
1190 1258
1191 difference = newpos - ci.curpos; 1259 difference = newpos - ci.curpos;
1192 if (difference >= 0) { 1260 if (difference >= 0)
1261 {
1193 /* Seeking forward */ 1262 /* Seeking forward */
1194 logf("seek: +%d", difference); 1263 logf("seek: +%d", difference);
1195 codec_advance_buffer_callback(difference); 1264 codec_advance_buffer_callback(difference);
@@ -1205,15 +1274,19 @@ static bool codec_seek_buffer_callback(size_t newpos)
1205 if (newpos < cur_ti->start_pos) 1274 if (newpos < cur_ti->start_pos)
1206 { 1275 {
1207 struct event ev; 1276 struct event ev;
1277
1208 queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos); 1278 queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos);
1279
1209 queue_wait(&codec_callback_queue, &ev); 1280 queue_wait(&codec_callback_queue, &ev);
1210 switch (ev.id) 1281 switch (ev.id)
1211 { 1282 {
1212 case Q_CODEC_REQUEST_COMPLETE: 1283 case Q_CODEC_REQUEST_COMPLETE:
1213 return true; 1284 return true;
1285
1214 case Q_CODEC_REQUEST_FAILED: 1286 case Q_CODEC_REQUEST_FAILED:
1215 ci.stop_codec = true; 1287 ci.stop_codec = true;
1216 return false; 1288 return false;
1289
1217 default: 1290 default:
1218 logf("Bad event on ccq"); 1291 logf("Bad event on ccq");
1219 return false; 1292 return false;
@@ -1300,6 +1373,7 @@ static void pcmbuf_track_changed_callback(void)
1300static bool yield_codecs(void) 1373static bool yield_codecs(void)
1301{ 1374{
1302 yield(); 1375 yield();
1376
1303 if (!queue_empty(&audio_queue)) return true; 1377 if (!queue_empty(&audio_queue)) return true;
1304 1378
1305 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata()) 1379 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
@@ -1308,6 +1382,7 @@ static bool yield_codecs(void)
1308 sleep(1); 1382 sleep(1);
1309 if (!queue_empty(&audio_queue)) return true; 1383 if (!queue_empty(&audio_queue)) return true;
1310 } 1384 }
1385
1311 return false; 1386 return false;
1312} 1387}
1313 1388
@@ -1351,7 +1426,8 @@ static void audio_read_file(bool quick)
1351 int rc; 1426 int rc;
1352 1427
1353 /* If we're called and no file is open, this is an error */ 1428 /* If we're called and no file is open, this is an error */
1354 if (current_fd < 0) { 1429 if (current_fd < 0)
1430 {
1355 logf("Bad fd in arf"); 1431 logf("Bad fd in arf");
1356 /* Stop this buffer cycle immediately */ 1432 /* Stop this buffer cycle immediately */
1357 fill_bytesleft = 0; 1433 fill_bytesleft = 0;
@@ -1360,7 +1436,8 @@ static void audio_read_file(bool quick)
1360 return ; 1436 return ;
1361 } 1437 }
1362 1438
1363 while (tracks[track_widx].filerem > 0) { 1439 while (tracks[track_widx].filerem > 0)
1440 {
1364 if (fill_bytesleft == 0) 1441 if (fill_bytesleft == 0)
1365 break ; 1442 break ;
1366 1443
@@ -1371,7 +1448,8 @@ static void audio_read_file(bool quick)
1371 /* rc is the actual amount read */ 1448 /* rc is the actual amount read */
1372 rc = read(current_fd, &filebuf[buf_widx], copy_n); 1449 rc = read(current_fd, &filebuf[buf_widx], copy_n);
1373 1450
1374 if (rc <= 0) { 1451 if (rc <= 0)
1452 {
1375 /* Reached the end of the file */ 1453 /* Reached the end of the file */
1376 tracks[track_widx].filerem = 0; 1454 tracks[track_widx].filerem = 0;
1377 break ; 1455 break ;
@@ -1396,17 +1474,20 @@ static void audio_read_file(bool quick)
1396 break; 1474 break;
1397 } 1475 }
1398 1476
1399 if (tracks[track_widx].filerem == 0) { 1477 if (tracks[track_widx].filerem == 0)
1478 {
1400 logf("Finished buf:%dB", tracks[track_widx].filesize); 1479 logf("Finished buf:%dB", tracks[track_widx].filesize);
1401 close(current_fd); 1480 close(current_fd);
1402 current_fd = -1; 1481 current_fd = -1;
1403 strip_id3v1_tag(); 1482 strip_id3v1_tag();
1404 1483
1405 if (++track_widx >= MAX_TRACK) 1484 track_widx++;
1406 track_widx = 0; 1485 track_widx &= MAX_TRACK_MASK;
1407 1486
1408 tracks[track_widx].filesize = 0; 1487 tracks[track_widx].filesize = 0;
1409 } else { 1488 }
1489 else
1490 {
1410 logf("Partially buf:%dB", 1491 logf("Partially buf:%dB",
1411 tracks[track_widx].filesize - tracks[track_widx].filerem); 1492 tracks[track_widx].filesize - tracks[track_widx].filerem);
1412 } 1493 }
@@ -1414,13 +1495,15 @@ static void audio_read_file(bool quick)
1414 1495
1415static void codec_discard_codec_callback(void) 1496static void codec_discard_codec_callback(void)
1416{ 1497{
1417 if (cur_ti->has_codec) { 1498 if (cur_ti->has_codec)
1499 {
1418 cur_ti->has_codec = false; 1500 cur_ti->has_codec = false;
1419 filebufused -= cur_ti->codecsize; 1501 filebufused -= cur_ti->codecsize;
1420 buf_ridx += cur_ti->codecsize; 1502 buf_ridx += cur_ti->codecsize;
1421 if (buf_ridx >= filebuflen) 1503 if (buf_ridx >= filebuflen)
1422 buf_ridx -= filebuflen; 1504 buf_ridx -= filebuflen;
1423 } 1505 }
1506
1424 /* Check if a buffer desync has happened, and log it */ 1507 /* Check if a buffer desync has happened, and log it */
1425 if (buf_ridx != cur_ti->buf_idx) 1508 if (buf_ridx != cur_ti->buf_idx)
1426 { 1509 {
@@ -1434,13 +1517,15 @@ static void codec_discard_codec_callback(void)
1434 filebufused += filebuflen; 1517 filebufused += filebuflen;
1435 filebufused -= track_ridx; 1518 filebufused -= track_ridx;
1436 /* If that was not the same amount as the track was off, log it */ 1519 /* If that was not the same amount as the track was off, log it */
1437 if (new_used != filebufused) { 1520 if (new_used != filebufused)
1521 {
1438 logf("Used off:%d",filebufused - new_used); 1522 logf("Used off:%d",filebufused - new_used);
1439 } 1523 }
1440 } 1524 }
1441} 1525}
1442 1526
1443static const char *get_codec_path(int codectype) { 1527static const char *get_codec_path(int codectype)
1528{
1444 switch (codectype) { 1529 switch (codectype) {
1445 case AFMT_OGG_VORBIS: 1530 case AFMT_OGG_VORBIS:
1446 logf("Codec: Vorbis"); 1531 logf("Codec: Vorbis");
@@ -1517,10 +1602,10 @@ static bool loadcodec(bool start_play)
1517 else 1602 else
1518 { 1603 {
1519 /* If we already have another track than this one buffered */ 1604 /* If we already have another track than this one buffered */
1520 if (track_widx != track_ridx) { 1605 if (track_widx != track_ridx)
1521 prev_track = track_widx - 1; 1606 {
1522 if (prev_track < 0) 1607 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1523 prev_track += MAX_TRACK; 1608
1524 /* If the previous codec is the same as this one, there is no need 1609 /* If the previous codec is the same as this one, there is no need
1525 * to put another copy of it on the file buffer */ 1610 * to put another copy of it on the file buffer */
1526 if (get_codec_base_type(tracks[track_widx].id3.codectype) == 1611 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
@@ -1540,15 +1625,18 @@ static bool loadcodec(bool start_play)
1540 } 1625 }
1541 1626
1542 size = filesize(fd); 1627 size = filesize(fd);
1628
1543 /* Never load a partial codec */ 1629 /* Never load a partial codec */
1544 if (fill_bytesleft < size) { 1630 if (fill_bytesleft < size)
1631 {
1545 logf("Not enough space"); 1632 logf("Not enough space");
1546 fill_bytesleft = 0; 1633 fill_bytesleft = 0;
1547 close(fd); 1634 close(fd);
1548 return false; 1635 return false;
1549 } 1636 }
1550 1637
1551 while (tracks[track_widx].codecsize < size) { 1638 while (tracks[track_widx].codecsize < size)
1639 {
1552 copy_n = MIN(conf_filechunk, filebuflen - buf_widx); 1640 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
1553 rc = read(fd, &filebuf[buf_widx], copy_n); 1641 rc = read(fd, &filebuf[buf_widx], copy_n);
1554 if (rc < 0) 1642 if (rc < 0)
@@ -1587,8 +1675,9 @@ static bool read_next_metadata(void)
1587 next_idx = track_widx; 1675 next_idx = track_widx;
1588 if (tracks[next_idx].taginfo_ready) 1676 if (tracks[next_idx].taginfo_ready)
1589 { 1677 {
1590 if (++next_idx >= MAX_TRACK) 1678 next_idx++;
1591 next_idx -= MAX_TRACK; 1679 next_idx &= MAX_TRACK_MASK;
1680
1592 if (tracks[next_idx].taginfo_ready) 1681 if (tracks[next_idx].taginfo_ready)
1593 return true; 1682 return true;
1594 } 1683 }
@@ -1603,7 +1692,8 @@ static bool read_next_metadata(void)
1603 1692
1604 status = get_metadata(&tracks[next_idx],fd,trackname,v1first); 1693 status = get_metadata(&tracks[next_idx],fd,trackname,v1first);
1605 /* Preload the glyphs in the tags */ 1694 /* Preload the glyphs in the tags */
1606 if (status) { 1695 if (status)
1696 {
1607 if (tracks[next_idx].id3.title) 1697 if (tracks[next_idx].id3.title)
1608 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL); 1698 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
1609 if (tracks[next_idx].id3.artist) 1699 if (tracks[next_idx].id3.artist)
@@ -1625,7 +1715,8 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1625 /* Stop buffer filling if there is no free track entries. 1715 /* Stop buffer filling if there is no free track entries.
1626 Don't fill up the last track entry (we wan't to store next track 1716 Don't fill up the last track entry (we wan't to store next track
1627 metadata there). */ 1717 metadata there). */
1628 if (!have_free_tracks()) { 1718 if (!have_free_tracks())
1719 {
1629 logf("No free tracks"); 1720 logf("No free tracks");
1630 return false; 1721 return false;
1631 } 1722 }
@@ -1641,18 +1732,21 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1641 peek_again: 1732 peek_again:
1642 logf("Buffering track:%d/%d", track_widx, track_ridx); 1733 logf("Buffering track:%d/%d", track_widx, track_ridx);
1643 /* Get track name from current playlist read position. */ 1734 /* Get track name from current playlist read position. */
1644 while ((trackname = playlist_peek(last_peek_offset)) != NULL) { 1735 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
1736 {
1645 /* Handle broken playlists. */ 1737 /* Handle broken playlists. */
1646 current_fd = open(trackname, O_RDONLY); 1738 current_fd = open(trackname, O_RDONLY);
1647 if (current_fd < 0) { 1739 if (current_fd < 0) {
1648 logf("Open failed"); 1740 logf("Open failed");
1649 /* Skip invalid entry from playlist. */ 1741 /* Skip invalid entry from playlist. */
1650 playlist_skip_entry(NULL, last_peek_offset); 1742 playlist_skip_entry(NULL, last_peek_offset);
1651 } else 1743 }
1744 else
1652 break; 1745 break;
1653 } 1746 }
1654 1747
1655 if (!trackname) { 1748 if (!trackname)
1749 {
1656 logf("End-of-playlist"); 1750 logf("End-of-playlist");
1657 playlist_end = true; 1751 playlist_end = true;
1658 return false; 1752 return false;
@@ -1665,8 +1759,10 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1665 tracks[track_widx].available = 0; 1759 tracks[track_widx].available = 0;
1666 1760
1667 /* Set default values */ 1761 /* Set default values */
1668 if (start_play) { 1762 if (start_play)
1763 {
1669 int last_codec = current_codec; 1764 int last_codec = current_codec;
1765
1670 current_codec = CODEC_IDX_AUDIO; 1766 current_codec = CODEC_IDX_AUDIO;
1671 conf_watermark = AUDIO_DEFAULT_WATERMARK; 1767 conf_watermark = AUDIO_DEFAULT_WATERMARK;
1672 conf_filechunk = AUDIO_DEFAULT_FILECHUNK; 1768 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
@@ -1675,19 +1771,26 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1675 } 1771 }
1676 1772
1677 /* Get track metadata if we don't already have it. */ 1773 /* Get track metadata if we don't already have it. */
1678 if (!tracks[track_widx].taginfo_ready) { 1774 if (!tracks[track_widx].taginfo_ready)
1679 if (get_metadata(&tracks[track_widx],current_fd,trackname,v1first)) { 1775 {
1680 if (start_play) { 1776 if (get_metadata(&tracks[track_widx],current_fd,trackname,v1first))
1777 {
1778 if (start_play)
1779 {
1681 track_changed = true; 1780 track_changed = true;
1682 playlist_update_resume_info(audio_current_track()); 1781 playlist_update_resume_info(audio_current_track());
1683 } 1782 }
1684 } else { 1783 }
1784 else
1785 {
1685 logf("mde:%s!",trackname); 1786 logf("mde:%s!",trackname);
1787
1686 /* Set filesize to zero to indicate no file was loaded. */ 1788 /* Set filesize to zero to indicate no file was loaded. */
1687 tracks[track_widx].filesize = 0; 1789 tracks[track_widx].filesize = 0;
1688 tracks[track_widx].filerem = 0; 1790 tracks[track_widx].filerem = 0;
1689 close(current_fd); 1791 close(current_fd);
1690 current_fd = -1; 1792 current_fd = -1;
1793
1691 /* Skip invalid entry from playlist. */ 1794 /* Skip invalid entry from playlist. */
1692 playlist_skip_entry(NULL, last_peek_offset); 1795 playlist_skip_entry(NULL, last_peek_offset);
1693 tracks[track_widx].taginfo_ready = false; 1796 tracks[track_widx].taginfo_ready = false;
@@ -1698,8 +1801,8 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1698 1801
1699 /* Load the codec. */ 1802 /* Load the codec. */
1700 tracks[track_widx].codecbuf = &filebuf[buf_widx]; 1803 tracks[track_widx].codecbuf = &filebuf[buf_widx];
1701 if (!loadcodec(start_play)) { 1804 if (!loadcodec(start_play))
1702 1805 {
1703 if (tracks[track_widx].codecsize) 1806 if (tracks[track_widx].codecsize)
1704 { 1807 {
1705 /* Must undo the buffer write of the partial codec */ 1808 /* Must undo the buffer write of the partial codec */
@@ -1719,7 +1822,8 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1719 current_fd = -1; 1822 current_fd = -1;
1720 1823
1721 /* Try skipping to next track if there is space. */ 1824 /* Try skipping to next track if there is space. */
1722 if (fill_bytesleft > 0) { 1825 if (fill_bytesleft > 0)
1826 {
1723 /* This is an error condition unless the fill_bytesleft is 0 */ 1827 /* This is an error condition unless the fill_bytesleft is 0 */
1724 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname); 1828 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
1725 /* We should not use gui_syncplash from audio thread! */ 1829 /* We should not use gui_syncplash from audio thread! */
@@ -1729,6 +1833,7 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1729 tracks[track_widx].taginfo_ready = false; 1833 tracks[track_widx].taginfo_ready = false;
1730 goto peek_again; 1834 goto peek_again;
1731 } 1835 }
1836
1732 return false; 1837 return false;
1733 } 1838 }
1734 1839
@@ -1736,7 +1841,8 @@ static bool audio_load_track(int offset, bool start_play, bool rebuffer)
1736 set_filebuf_watermark(buffer_margin); 1841 set_filebuf_watermark(buffer_margin);
1737 tracks[track_widx].id3.elapsed = 0; 1842 tracks[track_widx].id3.elapsed = 0;
1738 1843
1739 if (offset > 0) { 1844 if (offset > 0)
1845 {
1740 switch (tracks[track_widx].id3.codectype) { 1846 switch (tracks[track_widx].id3.codectype) {
1741 case AFMT_MPA_L1: 1847 case AFMT_MPA_L1:
1742 case AFMT_MPA_L2: 1848 case AFMT_MPA_L2:
@@ -1785,16 +1891,20 @@ static void audio_clear_track_entries(
1785 1891
1786 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered); 1892 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
1787 /* Loop over all tracks from write-to-read */ 1893 /* Loop over all tracks from write-to-read */
1788 while (1) { 1894 while (1)
1789 if (++cur_idx >= MAX_TRACK) 1895 {
1790 cur_idx -= MAX_TRACK; 1896 cur_idx++;
1897 cur_idx &= MAX_TRACK_MASK;
1898
1791 if (cur_idx == track_ridx) 1899 if (cur_idx == track_ridx)
1792 break; 1900 break;
1793 1901
1794 /* If the track is buffered, conditionally clear/notify, 1902 /* If the track is buffered, conditionally clear/notify,
1795 * otherwise clear the track if that option is selected */ 1903 * otherwise clear the track if that option is selected */
1796 if (tracks[cur_idx].event_sent) { 1904 if (tracks[cur_idx].event_sent)
1797 if (clear_buffered) { 1905 {
1906 if (clear_buffered)
1907 {
1798 if (last_idx >= 0) 1908 if (last_idx >= 0)
1799 { 1909 {
1800 /* If there is an unbuffer callback, call it, otherwise, 1910 /* If there is an unbuffer callback, call it, otherwise,
@@ -1806,7 +1916,8 @@ static void audio_clear_track_entries(
1806 } 1916 }
1807 last_idx = cur_idx; 1917 last_idx = cur_idx;
1808 } 1918 }
1809 } else if (clear_unbuffered) 1919 }
1920 else if (clear_unbuffered)
1810 memset(&tracks[cur_idx], 0, sizeof(struct track_info)); 1921 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
1811 } 1922 }
1812 1923
@@ -1846,15 +1957,19 @@ static void audio_stop_playback(void)
1846 } 1957 }
1847 1958
1848 if (voice_is_playing) 1959 if (voice_is_playing)
1960 {
1849 while (voice_is_playing || !queue_empty(&voice_codec_queue)) 1961 while (voice_is_playing || !queue_empty(&voice_codec_queue))
1850 yield(); 1962 yield();
1851 1963 }
1964
1852 filebufused = 0; 1965 filebufused = 0;
1853 playing = false; 1966 playing = false;
1854 filling = false; 1967 filling = false;
1855 paused = false; 1968 paused = false;
1856 stop_codec_flush(); 1969 stop_codec_flush();
1857 if (current_fd >= 0) { 1970
1971 if (current_fd >= 0)
1972 {
1858 close(current_fd); 1973 close(current_fd);
1859 current_fd = -1; 1974 current_fd = -1;
1860 } 1975 }
@@ -1882,7 +1997,8 @@ static void audio_play_start(size_t offset)
1882 ci.new_track = 0; 1997 ci.new_track = 0;
1883 ci.seek_time = 0; 1998 ci.seek_time = 0;
1884 1999
1885 if (current_fd >= 0) { 2000 if (current_fd >= 0)
2001 {
1886 close(current_fd); 2002 close(current_fd);
1887 current_fd = -1; 2003 current_fd = -1;
1888 } 2004 }
@@ -1908,10 +2024,13 @@ static void generate_postbuffer_events(void)
1908 2024
1909 logf("Postbuffer:%d/%d",track_ridx,track_widx); 2025 logf("Postbuffer:%d/%d",track_ridx,track_widx);
1910 2026
1911 if (have_tracks()) { 2027 if (have_tracks())
2028 {
1912 cur_idx = track_ridx; 2029 cur_idx = track_ridx;
2030
1913 while (1) { 2031 while (1) {
1914 if (!tracks[cur_idx].event_sent) { 2032 if (!tracks[cur_idx].event_sent)
2033 {
1915 if (last_idx >= 0 && !tracks[last_idx].event_sent) 2034 if (last_idx >= 0 && !tracks[last_idx].event_sent)
1916 { 2035 {
1917 /* Mark the event 'sent' even if we don't really send one */ 2036 /* Mark the event 'sent' even if we don't really send one */
@@ -1923,8 +2042,8 @@ static void generate_postbuffer_events(void)
1923 } 2042 }
1924 if (cur_idx == track_widx) 2043 if (cur_idx == track_widx)
1925 break; 2044 break;
1926 if (++cur_idx >= MAX_TRACK) 2045 cur_idx++;
1927 cur_idx -= MAX_TRACK; 2046 cur_idx &= MAX_TRACK_MASK;
1928 } 2047 }
1929 2048
1930 if (last_idx >= 0 && !tracks[last_idx].event_sent) 2049 if (last_idx >= 0 && !tracks[last_idx].event_sent)
@@ -2107,8 +2226,7 @@ void audio_invalidate_tracks(void)
2107 2226
2108 /* If the current track is fully buffered, advance the write pointer */ 2227 /* If the current track is fully buffered, advance the write pointer */
2109 if (tracks[track_widx].filerem == 0) 2228 if (tracks[track_widx].filerem == 0)
2110 if (++track_widx >= MAX_TRACK) 2229 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
2111 track_widx -= MAX_TRACK;
2112 2230
2113 /* Mark all other entries null (also buffered wrong metadata). */ 2231 /* Mark all other entries null (also buffered wrong metadata). */
2114 filebufused = cur_ti->available; 2232 filebufused = cur_ti->available;
@@ -2129,8 +2247,8 @@ static void audio_new_playlist(void)
2129 track_widx = track_ridx; 2247 track_widx = track_ridx;
2130 audio_clear_track_entries(true, true); 2248 audio_clear_track_entries(true, true);
2131 2249
2132 if (++track_widx >= MAX_TRACK) 2250 track_widx++;
2133 track_widx -= MAX_TRACK; 2251 track_widx &= MAX_TRACK_MASK;
2134 2252
2135 /* Stop reading the current track */ 2253 /* Stop reading the current track */
2136 cur_ti->filerem = 0; 2254 cur_ti->filerem = 0;
@@ -2146,6 +2264,7 @@ static void audio_new_playlist(void)
2146 if (buf_widx >= filebuflen) 2264 if (buf_widx >= filebuflen)
2147 buf_widx -= filebuflen; 2265 buf_widx -= filebuflen;
2148 } 2266 }
2267
2149 /* Signal the codec to initiate a track change forward */ 2268 /* Signal the codec to initiate a track change forward */
2150 new_playlist = true; 2269 new_playlist = true;
2151 ci.new_track = 1; 2270 ci.new_track = 1;
@@ -2357,19 +2476,26 @@ static void codec_thread(void)
2357 switch (ev.id) { 2476 switch (ev.id) {
2358 case Q_CODEC_LOAD_DISK: 2477 case Q_CODEC_LOAD_DISK:
2359 case Q_CODEC_LOAD: 2478 case Q_CODEC_LOAD:
2360 if (playing) { 2479 if (playing)
2480 {
2361 const char *codec_path; 2481 const char *codec_path;
2362 if (ci.new_track || status != CODEC_OK) { 2482
2363 if (!ci.new_track) { 2483 if (ci.new_track || status != CODEC_OK)
2484 {
2485 if (!ci.new_track)
2486 {
2364 logf("Codec failure"); 2487 logf("Codec failure");
2365 gui_syncsplash(HZ*2, true, "Codec failure"); 2488 gui_syncsplash(HZ*2, true, "Codec failure");
2366 } 2489 }
2490
2367 if (!load_next_track()) 2491 if (!load_next_track())
2368 { 2492 {
2369 queue_post(&codec_queue, Q_AUDIO_STOP, 0); 2493 queue_post(&codec_queue, Q_AUDIO_STOP, 0);
2370 break; 2494 break;
2371 } 2495 }
2372 } else { 2496 }
2497 else
2498 {
2373 logf("Codec finished"); 2499 logf("Codec finished");
2374 if (ci.stop_codec) 2500 if (ci.stop_codec)
2375 { 2501 {
@@ -2381,6 +2507,7 @@ static void codec_thread(void)
2381 break; 2507 break;
2382 } 2508 }
2383 } 2509 }
2510
2384 if (cur_ti->has_codec) 2511 if (cur_ti->has_codec)
2385 queue_post(&codec_queue, Q_CODEC_LOAD, 0); 2512 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2386 else 2513 else
@@ -2466,6 +2593,7 @@ void voice_init(void)
2466 queue_init(&voice_codec_queue); 2593 queue_init(&voice_codec_queue);
2467 voice_thread_num = create_thread(voice_codec_thread, voice_codec_stack, 2594 voice_thread_num = create_thread(voice_codec_thread, voice_codec_stack,
2468 sizeof(voice_codec_stack), voice_codec_thread_name); 2595 sizeof(voice_codec_stack), voice_codec_thread_name);
2596
2469 while (!voice_codec_loaded) 2597 while (!voice_codec_loaded)
2470 yield(); 2598 yield();
2471} 2599}
@@ -2475,12 +2603,10 @@ struct mp3entry* audio_current_track(void)
2475 const char *filename; 2603 const char *filename;
2476 const char *p; 2604 const char *p;
2477 static struct mp3entry temp_id3; 2605 static struct mp3entry temp_id3;
2478 int cur_idx = track_ridx + ci.new_track; 2606 int cur_idx;
2479 2607
2480 if (cur_idx >= MAX_TRACK) 2608 cur_idx = track_ridx + ci.new_track;
2481 cur_idx -= MAX_TRACK; 2609 cur_idx &= MAX_TRACK_MASK;
2482 else if (cur_idx < 0)
2483 cur_idx += MAX_TRACK;
2484 2610
2485 if (tracks[cur_idx].taginfo_ready) 2611 if (tracks[cur_idx].taginfo_ready)
2486 return &tracks[cur_idx].id3; 2612 return &tracks[cur_idx].id3;
@@ -2515,8 +2641,7 @@ struct mp3entry* audio_next_track(void)
2515 if (!have_tracks()) 2641 if (!have_tracks())
2516 return NULL; 2642 return NULL;
2517 2643
2518 if (++next_idx >= MAX_TRACK) 2644 next_idx &= MAX_TRACK_MASK;
2519 next_idx -= MAX_TRACK;
2520 2645
2521 if (!tracks[next_idx].taginfo_ready) 2646 if (!tracks[next_idx].taginfo_ready)
2522 return NULL; 2647 return NULL;
@@ -2526,7 +2651,8 @@ struct mp3entry* audio_next_track(void)
2526 2651
2527bool audio_has_changed_track(void) 2652bool audio_has_changed_track(void)
2528{ 2653{
2529 if (track_changed) { 2654 if (track_changed)
2655 {
2530 track_changed = false; 2656 track_changed = false;
2531 return true; 2657 return true;
2532 } 2658 }
@@ -2944,6 +3070,7 @@ void audio_preinit(void)
2944 cur_ti = &tracks[0]; 3070 cur_ti = &tracks[0];
2945 3071
2946 mutex_init(&mutex_codecthread); 3072 mutex_init(&mutex_codecthread);
3073 mutex_init(&mutex_buffering);
2947 3074
2948 queue_init(&audio_queue); 3075 queue_init(&audio_queue);
2949 queue_init(&codec_queue); 3076 queue_init(&codec_queue);