diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-07-29 17:25:31 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-07-29 17:25:31 +0000 |
commit | d43bff987ac3e0991802853192b447d5ebee64e0 (patch) | |
tree | fce5175bd876bee22c951ac461cde062352ff7b7 /apps/playback.c | |
parent | 78f425d17458deaac16cff2fdeff170f518e1dc6 (diff) | |
download | rockbox-d43bff987ac3e0991802853192b447d5ebee64e0.tar.gz rockbox-d43bff987ac3e0991802853192b447d5ebee64e0.zip |
Define MAX_TRACK_MAX and use it to keep the ring track structure
inside boundaries. Cleaned identation also.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10361 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 333 |
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 | ||
179 | static struct mutex mutex_codecthread; | 179 | static struct mutex mutex_codecthread; |
180 | static struct mutex mutex_buffering; | ||
180 | static struct event_queue codec_callback_queue; | 181 | static struct event_queue codec_callback_queue; |
181 | 182 | ||
182 | static struct mp3entry id3_voice; | 183 | static 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 | ||
477 | static void pcmbuf_position_callback(size_t size) ICODE_ATTR; | 486 | static void pcmbuf_position_callback(size_t size) ICODE_ATTR; |
478 | static void pcmbuf_position_callback(size_t size) { | 487 | static 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 | ||
489 | static void voice_set_elapsed_callback(unsigned int value) | 501 | static 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 | ||
512 | static void voice_set_offset_callback(size_t value) | 526 | static void voice_set_offset_callback(size_t value) |
@@ -517,6 +531,7 @@ static void voice_set_offset_callback(size_t value) | |||
517 | static void codec_set_offset_callback(size_t value) | 531 | static 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 | ||
550 | int audio_track_count(void) | 565 | int 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 | ||
562 | static void advance_buffer_counters(size_t amount) { | 580 | static 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 | ||
576 | static size_t voice_filebuf_callback(void *ptr, size_t size) | 599 | static 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 */ |
775 | static size_t buffer_count_tracks(int from_track, int to_track) { | 809 | static 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 | ||
817 | static bool buffer_wind_backward(int new_track_ridx, int old_track_ridx) { | 859 | static 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) | |||
878 | static void audio_rebuffer(void) | 930 | static 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) | |||
1132 | static void voice_advance_buffer_loc_callback(void *ptr) | 1194 | static 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 | ||
1138 | static void codec_advance_buffer_loc_callback(void *ptr) | 1201 | static 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 | ||
1144 | static off_t voice_mp3_get_filepos_callback(int newtime) | 1208 | static 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) | |||
1165 | static void codec_seek_complete_callback(void) | 1230 | static 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) | |||
1178 | static bool voice_seek_buffer_callback(size_t newpos) | 1245 | static 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) | |||
1300 | static bool yield_codecs(void) | 1373 | static 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 | ||
1415 | static void codec_discard_codec_callback(void) | 1496 | static 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 | ||
1443 | static const char *get_codec_path(int codectype) { | 1527 | static 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 | ||
2527 | bool audio_has_changed_track(void) | 2652 | bool 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); |