summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
authorZakk Roberts <midk@rockbox.org>2006-03-30 05:56:19 +0000
committerZakk Roberts <midk@rockbox.org>2006-03-30 05:56:19 +0000
commit8bdd92b05e2c87b0bae478610436f292c9d3b952 (patch)
tree933ab56bb76ac4035013546aaae1cce59c7444a9 /apps/playback.c
parentdbcc9c25d5d73a01eb5a65473245bfec69371fe9 (diff)
downloadrockbox-8bdd92b05e2c87b0bae478610436f292c9d3b952.tar.gz
rockbox-8bdd92b05e2c87b0bae478610436f292c9d3b952.zip
New 'Track Skip Only' option for Crossfading; crossfading is disabled except for manual track changes. NOTE: If you were using 'Always' mode previously, check again after updating: you'll now be in the new 'Track Skip Only' mode.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9353 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c379
1 files changed, 190 insertions, 189 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 80811c2d81..7b20beba23 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -104,7 +104,7 @@ enum {
104 Q_AUDIO_DIR_PREV, 104 Q_AUDIO_DIR_PREV,
105 Q_AUDIO_SEAMLESS_SEEK, 105 Q_AUDIO_SEAMLESS_SEEK,
106 Q_AUDIO_POSTINIT, 106 Q_AUDIO_POSTINIT,
107 107
108 Q_CODEC_LOAD, 108 Q_CODEC_LOAD,
109 Q_CODEC_LOAD_DISK, 109 Q_CODEC_LOAD_DISK,
110}; 110};
@@ -272,7 +272,7 @@ static void voice_boost_cpu(bool state)
272 272
273 if (!voice_codec_loaded) 273 if (!voice_codec_loaded)
274 state = false; 274 state = false;
275 275
276 if (state != voice_cpu_boosted) 276 if (state != voice_cpu_boosted)
277 { 277 {
278 cpu_boost(state); 278 cpu_boost(state);
@@ -309,7 +309,7 @@ bool codec_pcmbuf_insert_split_callback(const void *ch1, const void *ch2,
309 } 309 }
310 else 310 else
311 { 311 {
312 if (ci.reload_codec || ci.stop_codec) 312 if (ci.reload_codec || ci.stop_codec)
313 return true; 313 return true;
314 314
315 while ((dest = pcmbuf_request_buffer(est_output_size, 315 while ((dest = pcmbuf_request_buffer(est_output_size,
@@ -323,7 +323,7 @@ bool codec_pcmbuf_insert_split_callback(const void *ch1, const void *ch2,
323 /* Get the real input_size for output_size bytes, guarding 323 /* Get the real input_size for output_size bytes, guarding
324 * against resampling buffer overflows. */ 324 * against resampling buffer overflows. */
325 input_size = dsp_input_size(output_size); 325 input_size = dsp_input_size(output_size);
326 326
327 if (input_size <= 0) { 327 if (input_size <= 0) {
328 DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n", 328 DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n",
329 output_size, length, input_size); 329 output_size, length, input_size);
@@ -336,7 +336,7 @@ bool codec_pcmbuf_insert_split_callback(const void *ch1, const void *ch2,
336 output_size, length, input_size, length); 336 output_size, length, input_size, length);
337 input_size = length; 337 input_size = length;
338 } 338 }
339 339
340 output_size = dsp_process(dest, src, input_size); 340 output_size = dsp_process(dest, src, input_size);
341 341
342 /* Hotswap between audio and voice codecs as necessary. */ 342 /* Hotswap between audio and voice codecs as necessary. */
@@ -364,7 +364,7 @@ bool codec_pcmbuf_insert_split_callback(const void *ch1, const void *ch2,
364 } 364 }
365 break ; 365 break ;
366 } 366 }
367 367
368 length -= input_size; 368 length -= input_size;
369 } 369 }
370 370
@@ -416,15 +416,15 @@ void codec_set_elapsed_callback(unsigned int value)
416 /* We don't save or display offsets for voice */ 416 /* We don't save or display offsets for voice */
417 if (current_codec == CODEC_IDX_VOICE) 417 if (current_codec == CODEC_IDX_VOICE)
418 return ; 418 return ;
419 419
420#ifdef AB_REPEAT_ENABLE 420#ifdef AB_REPEAT_ENABLE
421 ab_position_report(value); 421 ab_position_report(value);
422#endif 422#endif
423 latency = pcmbuf_get_latency(); 423 latency = pcmbuf_get_latency();
424 424
425 if (value < latency) { 425 if (value < latency) {
426 cur_ti->id3.elapsed = 0; 426 cur_ti->id3.elapsed = 0;
427 } else if (value - latency > cur_ti->id3.elapsed 427 } else if (value - latency > cur_ti->id3.elapsed
428 || value - latency < cur_ti->id3.elapsed - 2) { 428 || value - latency < cur_ti->id3.elapsed - 2) {
429 cur_ti->id3.elapsed = value - latency; 429 cur_ti->id3.elapsed = value - latency;
430 } 430 }
@@ -437,9 +437,9 @@ void codec_set_offset_callback(size_t value)
437 /* We don't save or display offsets for voice */ 437 /* We don't save or display offsets for voice */
438 if (current_codec == CODEC_IDX_VOICE) 438 if (current_codec == CODEC_IDX_VOICE)
439 return ; 439 return ;
440 440
441 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8; 441 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
442 442
443 if (value < latency) { 443 if (value < latency) {
444 cur_ti->id3.offset = 0; 444 cur_ti->id3.offset = 0;
445 } else { 445 } else {
@@ -462,25 +462,25 @@ size_t codec_filebuf_callback(void *ptr, size_t size)
462 char *buf = (char *)ptr; 462 char *buf = (char *)ptr;
463 size_t copy_n; 463 size_t copy_n;
464 size_t part_n; 464 size_t part_n;
465 465
466 if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE) 466 if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
467 return 0; 467 return 0;
468 468
469 /* The ammount to copy is the lesser of the requested amount and the 469 /* The ammount to copy is the lesser of the requested amount and the
470 * amount left of the current track (both on disk and already loaded) */ 470 * amount left of the current track (both on disk and already loaded) */
471 copy_n = MIN(size, cur_ti->available + cur_ti->filerem); 471 copy_n = MIN(size, cur_ti->available + cur_ti->filerem);
472 472
473 /* Nothing requested OR nothing left */ 473 /* Nothing requested OR nothing left */
474 if (copy_n == 0) 474 if (copy_n == 0)
475 return 0; 475 return 0;
476 476
477 /* Let the disk buffer catch fill until enough data is available */ 477 /* Let the disk buffer catch fill until enough data is available */
478 while (copy_n > cur_ti->available) { 478 while (copy_n > cur_ti->available) {
479 yield(); 479 yield();
480 if (ci.stop_codec || ci.reload_codec) 480 if (ci.stop_codec || ci.reload_codec)
481 return 0; 481 return 0;
482 } 482 }
483 483
484 /* Copy as much as possible without wrapping */ 484 /* Copy as much as possible without wrapping */
485 part_n = MIN(copy_n, filebuflen - buf_ridx); 485 part_n = MIN(copy_n, filebuflen - buf_ridx);
486 memcpy(buf, &filebuf[buf_ridx], part_n); 486 memcpy(buf, &filebuf[buf_ridx], part_n);
@@ -488,10 +488,10 @@ size_t codec_filebuf_callback(void *ptr, size_t size)
488 if (part_n < copy_n) { 488 if (part_n < copy_n) {
489 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n); 489 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
490 } 490 }
491 491
492 /* Update read and other position pointers */ 492 /* Update read and other position pointers */
493 advance_buffer_counters(copy_n); 493 advance_buffer_counters(copy_n);
494 494
495 /* Return the actual amount of data copied to the buffer */ 495 /* Return the actual amount of data copied to the buffer */
496 return copy_n; 496 return copy_n;
497} 497}
@@ -514,7 +514,7 @@ void* voice_request_data(size_t *realsize, size_t reqsize)
514 pcmbuf_boost(false); 514 pcmbuf_boost(false);
515 sleep(HZ/16); 515 sleep(HZ/16);
516 } 516 }
517 517
518 if (voice_remaining) 518 if (voice_remaining)
519 { 519 {
520 voice_is_playing = true; 520 voice_is_playing = true;
@@ -549,18 +549,18 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
549 if (current_codec == CODEC_IDX_VOICE) { 549 if (current_codec == CODEC_IDX_VOICE) {
550 return voice_request_data(realsize, reqsize); 550 return voice_request_data(realsize, reqsize);
551 } 551 }
552 552
553 if (ci.stop_codec || !playing) { 553 if (ci.stop_codec || !playing) {
554 *realsize = 0; 554 *realsize = 0;
555 return NULL; 555 return NULL;
556 } 556 }
557 557
558 copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem); 558 copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem);
559 if (copy_n == 0) { 559 if (copy_n == 0) {
560 *realsize = 0; 560 *realsize = 0;
561 return NULL; 561 return NULL;
562 } 562 }
563 563
564 while (copy_n > cur_ti->available) { 564 while (copy_n > cur_ti->available) {
565 yield(); 565 yield();
566 if (ci.stop_codec || ci.reload_codec) { 566 if (ci.stop_codec || ci.reload_codec) {
@@ -568,7 +568,7 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
568 return NULL; 568 return NULL;
569 } 569 }
570 } 570 }
571 571
572 /* How much is left at the end of the file buffer before wrap? */ 572 /* How much is left at the end of the file buffer before wrap? */
573 buf_rem = filebuflen - buf_ridx; 573 buf_rem = filebuflen - buf_ridx;
574 /* If we can't satisfy the request without wrapping */ 574 /* If we can't satisfy the request without wrapping */
@@ -581,7 +581,7 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
581 else 581 else
582 copy_n = buf_rem; 582 copy_n = buf_rem;
583 } 583 }
584 584
585 *realsize = copy_n; 585 *realsize = copy_n;
586 return (char *)&filebuf[buf_ridx]; 586 return (char *)&filebuf[buf_ridx];
587} 587}
@@ -603,7 +603,7 @@ static bool rebuffer_and_seek(size_t newpos)
603 if (current_fd >= 0) 603 if (current_fd >= 0)
604 close(current_fd); 604 close(current_fd);
605 current_fd = fd; 605 current_fd = fd;
606 606
607 /* Clear codec buffer. */ 607 /* Clear codec buffer. */
608 audio_invalidate_tracks(); 608 audio_invalidate_tracks();
609 filebufused = 0; 609 filebufused = 0;
@@ -623,7 +623,7 @@ static bool rebuffer_and_seek(size_t newpos)
623 if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue)) 623 if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue))
624 return false; 624 return false;
625 } 625 }
626 626
627 return true; 627 return true;
628} 628}
629 629
@@ -634,22 +634,22 @@ void codec_advance_buffer_callback(size_t amount)
634 amount = MIN(amount, voice_remaining); 634 amount = MIN(amount, voice_remaining);
635 voicebuf += amount; 635 voicebuf += amount;
636 voice_remaining -= amount; 636 voice_remaining -= amount;
637 637
638 return ; 638 return ;
639 } 639 }
640 640
641 if (amount > cur_ti->available + cur_ti->filerem) 641 if (amount > cur_ti->available + cur_ti->filerem)
642 amount = cur_ti->available + cur_ti->filerem; 642 amount = cur_ti->available + cur_ti->filerem;
643 643
644 while (amount > cur_ti->available && filling) 644 while (amount > cur_ti->available && filling)
645 sleep(1); 645 sleep(1);
646 646
647 if (amount > cur_ti->available) { 647 if (amount > cur_ti->available) {
648 if (!rebuffer_and_seek(ci.curpos + amount)) 648 if (!rebuffer_and_seek(ci.curpos + amount))
649 ci.stop_codec = true; 649 ci.stop_codec = true;
650 return ; 650 return ;
651 } 651 }
652 652
653 advance_buffer_counters(amount); 653 advance_buffer_counters(amount);
654 654
655 codec_set_offset_callback(ci.curpos); 655 codec_set_offset_callback(ci.curpos);
@@ -672,7 +672,7 @@ off_t codec_mp3_get_filepos_callback(int newtime)
672 672
673 cur_ti->id3.elapsed = newtime; 673 cur_ti->id3.elapsed = newtime;
674 newpos = mp3_get_file_pos(); 674 newpos = mp3_get_file_pos();
675 675
676 return newpos; 676 return newpos;
677} 677}
678 678
@@ -688,10 +688,10 @@ bool codec_seek_buffer_callback(size_t newpos)
688 688
689 if (current_codec == CODEC_IDX_VOICE) 689 if (current_codec == CODEC_IDX_VOICE)
690 return false; 690 return false;
691 691
692 if (newpos >= cur_ti->filesize) 692 if (newpos >= cur_ti->filesize)
693 newpos = cur_ti->filesize - 1; 693 newpos = cur_ti->filesize - 1;
694 694
695 difference = newpos - ci.curpos; 695 difference = newpos - ci.curpos;
696 /* Seeking forward */ 696 /* Seeking forward */
697 if (difference >= 0) { 697 if (difference >= 0) {
@@ -704,7 +704,7 @@ bool codec_seek_buffer_callback(size_t newpos)
704 difference = -difference; 704 difference = -difference;
705 if (ci.curpos - difference < 0) 705 if (ci.curpos - difference < 0)
706 difference = ci.curpos; 706 difference = ci.curpos;
707 707
708 /* We need to reload the song. */ 708 /* We need to reload the song. */
709 if (newpos < cur_ti->start_pos) 709 if (newpos < cur_ti->start_pos)
710 return rebuffer_and_seek(newpos); 710 return rebuffer_and_seek(newpos);
@@ -717,7 +717,7 @@ bool codec_seek_buffer_callback(size_t newpos)
717 buf_ridx += filebuflen; 717 buf_ridx += filebuflen;
718 buf_ridx -= difference; 718 buf_ridx -= difference;
719 ci.curpos -= difference; 719 ci.curpos -= difference;
720 720
721 return true; 721 return true;
722} 722}
723 723
@@ -730,7 +730,7 @@ static void set_filebuf_watermark(int seconds)
730 730
731 if (!filebuf) 731 if (!filebuf)
732 return; /* Audio buffers not yet set up */ 732 return; /* Audio buffers not yet set up */
733 733
734 bytes = MAX(cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark); 734 bytes = MAX(cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
735 bytes = MIN(bytes, filebuflen / 2); 735 bytes = MIN(bytes, filebuflen / 2);
736 conf_watermark = bytes; 736 conf_watermark = bytes;
@@ -743,11 +743,11 @@ static void codec_configure_callback(int setting, void *value)
743 conf_watermark = (unsigned long)value; 743 conf_watermark = (unsigned long)value;
744 set_filebuf_watermark(buffer_margin); 744 set_filebuf_watermark(buffer_margin);
745 break; 745 break;
746 746
747 case CODEC_SET_FILEBUF_CHUNKSIZE: 747 case CODEC_SET_FILEBUF_CHUNKSIZE:
748 conf_filechunk = (unsigned long)value; 748 conf_filechunk = (unsigned long)value;
749 break; 749 break;
750 750
751 case CODEC_DSP_ENABLE: 751 case CODEC_DSP_ENABLE:
752 if ((bool)value) 752 if ((bool)value)
753 ci.pcmbuf_insert = codec_pcmbuf_insert_callback; 753 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
@@ -819,21 +819,21 @@ void strip_id3v1_tag(void)
819 tagptr = filebuflen + buf_widx - 128; 819 tagptr = filebuflen + buf_widx - 128;
820 else 820 else
821 tagptr = buf_widx - 128; 821 tagptr = buf_widx - 128;
822 822
823 for(i = 0;i < 3;i++) 823 for(i = 0;i < 3;i++)
824 { 824 {
825 if(tagptr >= filebuflen) 825 if(tagptr >= filebuflen)
826 tagptr -= filebuflen; 826 tagptr -= filebuflen;
827 827
828 if(filebuf[tagptr] != tag[i]) 828 if(filebuf[tagptr] != tag[i])
829 { 829 {
830 found = false; 830 found = false;
831 break; 831 break;
832 } 832 }
833 833
834 tagptr++; 834 tagptr++;
835 } 835 }
836 836
837 if(found) 837 if(found)
838 { 838 {
839 /* Skip id3v1 tag */ 839 /* Skip id3v1 tag */
@@ -858,14 +858,14 @@ static void audio_fill_file_buffer(void)
858 /* Throw away buffered codec. */ 858 /* Throw away buffered codec. */
859 if (tracks[track_widx].start_pos != 0) 859 if (tracks[track_widx].start_pos != 0)
860 tracks[track_widx].codecsize = 0; 860 tracks[track_widx].codecsize = 0;
861 861
862 mutex_lock(&mutex_bufferfill); 862 mutex_lock(&mutex_bufferfill);
863 i = 0; 863 i = 0;
864 size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE); 864 size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE);
865 while (i < size) { 865 while (i < size) {
866 /* Give codecs some processing time. */ 866 /* Give codecs some processing time. */
867 yield_codecs(); 867 yield_codecs();
868 868
869 if (fill_bytesleft == 0) 869 if (fill_bytesleft == 0)
870 break ; 870 break ;
871 copy_n = MIN(conf_filechunk, filebuflen - buf_widx); 871 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
@@ -875,7 +875,7 @@ static void audio_fill_file_buffer(void)
875 tracks[track_widx].filerem = 0; 875 tracks[track_widx].filerem = 0;
876 break ; 876 break ;
877 } 877 }
878 878
879 buf_widx += rc; 879 buf_widx += rc;
880 if (buf_widx >= filebuflen) 880 if (buf_widx >= filebuflen)
881 buf_widx -= filebuflen; 881 buf_widx -= filebuflen;
@@ -892,7 +892,7 @@ static void audio_fill_file_buffer(void)
892 } 892 }
893 893
894 mutex_unlock(&mutex_bufferfill); 894 mutex_unlock(&mutex_bufferfill);
895 895
896 /*logf("Filled:%d/%d", tracks[track_widx].available, 896 /*logf("Filled:%d/%d", tracks[track_widx].available,
897 tracks[track_widx].filerem);*/ 897 tracks[track_widx].filerem);*/
898} 898}
@@ -918,7 +918,7 @@ static bool loadcodec(bool start_play)
918 const char *codec_path; 918 const char *codec_path;
919 size_t copy_n; 919 size_t copy_n;
920 int prev_track; 920 int prev_track;
921 921
922 switch (tracks[track_widx].id3.codectype) { 922 switch (tracks[track_widx].id3.codectype) {
923 case AFMT_OGG_VORBIS: 923 case AFMT_OGG_VORBIS:
924 logf("Codec: Vorbis"); 924 logf("Codec: Vorbis");
@@ -971,14 +971,14 @@ static bool loadcodec(bool start_play)
971 codec_path = NULL; 971 codec_path = NULL;
972 return false; 972 return false;
973 } 973 }
974 974
975 tracks[track_widx].codecsize = 0; 975 tracks[track_widx].codecsize = 0;
976 976
977 if (!start_play) { 977 if (!start_play) {
978 prev_track = track_widx - 1; 978 prev_track = track_widx - 1;
979 if (prev_track < 0) 979 if (prev_track < 0)
980 prev_track = MAX_TRACK-1; 980 prev_track = MAX_TRACK-1;
981 if (track_count > 0 && 981 if (track_count > 0 &&
982 get_codec_base_type(tracks[track_widx].id3.codectype) == 982 get_codec_base_type(tracks[track_widx].id3.codectype) ==
983 get_codec_base_type(tracks[prev_track].id3.codectype)) 983 get_codec_base_type(tracks[prev_track].id3.codectype))
984 { 984 {
@@ -997,13 +997,13 @@ static bool loadcodec(bool start_play)
997 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path); 997 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path);
998 return true; 998 return true;
999 } 999 }
1000 1000
1001 fd = open(codec_path, O_RDONLY); 1001 fd = open(codec_path, O_RDONLY);
1002 if (fd < 0) { 1002 if (fd < 0) {
1003 logf("Codec doesn't exist!"); 1003 logf("Codec doesn't exist!");
1004 return false; 1004 return false;
1005 } 1005 }
1006 1006
1007 size = filesize(fd); 1007 size = filesize(fd);
1008 if (fill_bytesleft < size + conf_watermark) { 1008 if (fill_bytesleft < size + conf_watermark) {
1009 logf("Not enough space"); 1009 logf("Not enough space");
@@ -1013,11 +1013,11 @@ static bool loadcodec(bool start_play)
1013 close(fd); 1013 close(fd);
1014 return false; 1014 return false;
1015 } 1015 }
1016 1016
1017 i = 0; 1017 i = 0;
1018 while (i < size) { 1018 while (i < size) {
1019 yield_codecs(); 1019 yield_codecs();
1020 1020
1021 copy_n = MIN(conf_filechunk, filebuflen - buf_widx); 1021 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
1022 rc = read(fd, &filebuf[buf_widx], copy_n); 1022 rc = read(fd, &filebuf[buf_widx], copy_n);
1023 if (rc < 0) 1023 if (rc < 0)
@@ -1031,9 +1031,9 @@ static bool loadcodec(bool start_play)
1031 } 1031 }
1032 close(fd); 1032 close(fd);
1033 logf("Done: %dB", i); 1033 logf("Done: %dB", i);
1034 1034
1035 tracks[track_widx].codecsize = size; 1035 tracks[track_widx].codecsize = size;
1036 1036
1037 return true; 1037 return true;
1038} 1038}
1039 1039
@@ -1047,13 +1047,13 @@ static bool read_next_metadata(void)
1047 next_track = track_widx; 1047 next_track = track_widx;
1048 if (tracks[track_widx].taginfo_ready) 1048 if (tracks[track_widx].taginfo_ready)
1049 next_track++; 1049 next_track++;
1050 1050
1051 if (next_track >= MAX_TRACK) 1051 if (next_track >= MAX_TRACK)
1052 next_track -= MAX_TRACK; 1052 next_track -= MAX_TRACK;
1053 1053
1054 if (tracks[next_track].taginfo_ready) 1054 if (tracks[next_track].taginfo_ready)
1055 return true; 1055 return true;
1056 1056
1057 trackname = playlist_peek(last_peek_offset + 1); 1057 trackname = playlist_peek(last_peek_offset + 1);
1058 if (!trackname) 1058 if (!trackname)
1059 return false; 1059 return false;
@@ -1061,7 +1061,7 @@ static bool read_next_metadata(void)
1061 fd = open(trackname, O_RDONLY); 1061 fd = open(trackname, O_RDONLY);
1062 if (fd < 0) 1062 if (fd < 0)
1063 return false; 1063 return false;
1064 1064
1065 /** Start buffer refilling also because we need to spin-up the disk. 1065 /** Start buffer refilling also because we need to spin-up the disk.
1066 * In fact, it might be better not to start filling here, because if user 1066 * In fact, it might be better not to start filling here, because if user
1067 * is manipulating the playlist a lot, we will just lose battery. */ 1067 * is manipulating the playlist a lot, we will just lose battery. */
@@ -1119,13 +1119,13 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1119 } 1119 }
1120 break ; 1120 break ;
1121 } 1121 }
1122 1122
1123 if (!trackname) { 1123 if (!trackname) {
1124 logf("End-of-playlist"); 1124 logf("End-of-playlist");
1125 playlist_end = true; 1125 playlist_end = true;
1126 return false; 1126 return false;
1127 } 1127 }
1128 1128
1129 /* Initialize track entry. */ 1129 /* Initialize track entry. */
1130 size = filesize(fd); 1130 size = filesize(fd);
1131 tracks[track_widx].filerem = size; 1131 tracks[track_widx].filerem = size;
@@ -1135,10 +1135,10 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1135 //tracks[track_widx].taginfo_ready = false; 1135 //tracks[track_widx].taginfo_ready = false;
1136 tracks[track_widx].playlist_offset = peek_offset; 1136 tracks[track_widx].playlist_offset = peek_offset;
1137 last_peek_offset = peek_offset; 1137 last_peek_offset = peek_offset;
1138 1138
1139 if (buf_widx >= filebuflen) 1139 if (buf_widx >= filebuflen)
1140 buf_widx -= filebuflen; 1140 buf_widx -= filebuflen;
1141 1141
1142 /* Set default values */ 1142 /* Set default values */
1143 if (start_play) { 1143 if (start_play) {
1144 int last_codec = current_codec; 1144 int last_codec = current_codec;
@@ -1164,7 +1164,7 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1164 goto peek_again; 1164 goto peek_again;
1165 } 1165 }
1166 } 1166 }
1167 1167
1168 /* Load the codec. */ 1168 /* Load the codec. */
1169 tracks[track_widx].codecbuf = &filebuf[buf_widx]; 1169 tracks[track_widx].codecbuf = &filebuf[buf_widx];
1170 if (!loadcodec(start_play)) { 1170 if (!loadcodec(start_play)) {
@@ -1172,7 +1172,7 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1172 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname); 1172 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
1173 gui_syncsplash(HZ*2, true, msgbuf); 1173 gui_syncsplash(HZ*2, true, msgbuf);
1174 close(fd); 1174 close(fd);
1175 1175
1176 /* Set filesize to zero to indicate no file was loaded. */ 1176 /* Set filesize to zero to indicate no file was loaded. */
1177 tracks[track_widx].filesize = 0; 1177 tracks[track_widx].filesize = 0;
1178 tracks[track_widx].filerem = 0; 1178 tracks[track_widx].filerem = 0;
@@ -1220,7 +1220,7 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1220 break; 1220 break;
1221 } 1221 }
1222 } 1222 }
1223 1223
1224 if (start_play) { 1224 if (start_play) {
1225 track_count++; 1225 track_count++;
1226 codec_track_changed(); 1226 codec_track_changed();
@@ -1233,10 +1233,10 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1233 while (i < size) { 1233 while (i < size) {
1234 /* Give codecs some processing time to prevent glitches. */ 1234 /* Give codecs some processing time to prevent glitches. */
1235 yield_codecs(); 1235 yield_codecs();
1236 1236
1237 if (fill_bytesleft == 0) 1237 if (fill_bytesleft == 0)
1238 break ; 1238 break ;
1239 1239
1240 copy_n = MIN(conf_filechunk, filebuflen - buf_widx); 1240 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
1241 copy_n = MIN(size - i, copy_n); 1241 copy_n = MIN(size - i, copy_n);
1242 copy_n = MIN((int)fill_bytesleft, copy_n); 1242 copy_n = MIN((int)fill_bytesleft, copy_n);
@@ -1259,17 +1259,17 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1259 fill_bytesleft -= rc; 1259 fill_bytesleft -= rc;
1260 } 1260 }
1261 mutex_unlock(&mutex_bufferfill); 1261 mutex_unlock(&mutex_bufferfill);
1262 1262
1263 if (!start_play) 1263 if (!start_play)
1264 track_count++; 1264 track_count++;
1265 1265
1266 tracks[track_widx].filepos = i; 1266 tracks[track_widx].filepos = i;
1267 1267
1268 if (current_fd >= 0) { 1268 if (current_fd >= 0) {
1269 close(current_fd); 1269 close(current_fd);
1270 current_fd = -1; 1270 current_fd = -1;
1271 } 1271 }
1272 1272
1273 /* Leave the file handle open for faster buffer refill. */ 1273 /* Leave the file handle open for faster buffer refill. */
1274 if (tracks[track_widx].filerem != 0) { 1274 if (tracks[track_widx].filerem != 0) {
1275 current_fd = fd; 1275 current_fd = fd;
@@ -1279,13 +1279,13 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
1279 close(fd); 1279 close(fd);
1280 1280
1281 strip_id3v1_tag(); 1281 strip_id3v1_tag();
1282 1282
1283 if (++track_widx >= MAX_TRACK) { 1283 if (++track_widx >= MAX_TRACK) {
1284 track_widx = 0; 1284 track_widx = 0;
1285 } 1285 }
1286 tracks[track_widx].filerem = 0; 1286 tracks[track_widx].filerem = 0;
1287 } 1287 }
1288 1288
1289 return true; 1289 return true;
1290} 1290}
1291 1291
@@ -1293,7 +1293,7 @@ static void audio_clear_track_entries(bool buffered_only)
1293{ 1293{
1294 int cur_idx, event_count; 1294 int cur_idx, event_count;
1295 int i; 1295 int i;
1296 1296
1297 cur_idx = track_widx; 1297 cur_idx = track_widx;
1298 event_count = 0; 1298 event_count = 0;
1299 for (i = 0; i < MAX_TRACK - track_count; i++) { 1299 for (i = 0; i < MAX_TRACK - track_count; i++) {
@@ -1302,14 +1302,14 @@ static void audio_clear_track_entries(bool buffered_only)
1302 1302
1303 if (tracks[cur_idx].event_sent) 1303 if (tracks[cur_idx].event_sent)
1304 event_count++; 1304 event_count++;
1305 1305
1306 if (!track_unbuffer_callback) 1306 if (!track_unbuffer_callback)
1307 memset(&tracks[cur_idx], 0, sizeof(struct track_info)); 1307 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
1308 } 1308 }
1309 1309
1310 if (!track_unbuffer_callback) 1310 if (!track_unbuffer_callback)
1311 return ; 1311 return ;
1312 1312
1313 cur_idx = track_widx; 1313 cur_idx = track_widx;
1314 for (i = 0; i < MAX_TRACK - track_count; i++) { 1314 for (i = 0; i < MAX_TRACK - track_count; i++) {
1315 if (++cur_idx >= MAX_TRACK) 1315 if (++cur_idx >= MAX_TRACK)
@@ -1348,7 +1348,7 @@ static void audio_stop_playback(bool resume)
1348 close(current_fd); 1348 close(current_fd);
1349 current_fd = -1; 1349 current_fd = -1;
1350 } 1350 }
1351 1351
1352 track_count = 0; 1352 track_count = 0;
1353 /* Mark all entries null. */ 1353 /* Mark all entries null. */
1354 audio_clear_track_entries(false); 1354 audio_clear_track_entries(false);
@@ -1370,11 +1370,11 @@ static void audio_play_start(long offset)
1370 buf_widx = 0; 1370 buf_widx = 0;
1371 filebufused = 0; 1371 filebufused = 0;
1372 pcmbuf_set_boost_mode(true); 1372 pcmbuf_set_boost_mode(true);
1373 1373
1374 fill_bytesleft = filebuflen; 1374 fill_bytesleft = filebuflen;
1375 filling = true; 1375 filling = true;
1376 last_peek_offset = -1; 1376 last_peek_offset = -1;
1377 1377
1378 if (audio_load_track(offset, true, 0)) { 1378 if (audio_load_track(offset, true, 0)) {
1379 if (track_buffer_callback) { 1379 if (track_buffer_callback) {
1380 cur_ti->event_sent = true; 1380 cur_ti->event_sent = true;
@@ -1393,7 +1393,7 @@ static void generate_postbuffer_events(void)
1393{ 1393{
1394 int i; 1394 int i;
1395 int cur_ridx, event_count; 1395 int cur_ridx, event_count;
1396 1396
1397 /* At first determine how many unsent events we have. */ 1397 /* At first determine how many unsent events we have. */
1398 cur_ridx = track_ridx; 1398 cur_ridx = track_ridx;
1399 event_count = 0; 1399 event_count = 0;
@@ -1423,31 +1423,31 @@ static void generate_postbuffer_events(void)
1423static void initialize_buffer_fill(void) 1423static void initialize_buffer_fill(void)
1424{ 1424{
1425 int cur_idx, i; 1425 int cur_idx, i;
1426 1426
1427 /* Initialize only once; do not truncate the tracks. */ 1427 /* Initialize only once; do not truncate the tracks. */
1428 if (filling) 1428 if (filling)
1429 return ; 1429 return ;
1430 1430
1431 /* Save the current resume position once. */ 1431 /* Save the current resume position once. */
1432 playlist_update_resume_info(audio_current_track()); 1432 playlist_update_resume_info(audio_current_track());
1433 1433
1434 fill_bytesleft = filebuflen - filebufused; 1434 fill_bytesleft = filebuflen - filebufused;
1435 cur_ti->start_pos = ci.curpos; 1435 cur_ti->start_pos = ci.curpos;
1436 1436
1437 pcmbuf_set_boost_mode(true); 1437 pcmbuf_set_boost_mode(true);
1438 1438
1439 filling = true; 1439 filling = true;
1440 1440
1441 /* Calculate real track count after throwing away old tracks. */ 1441 /* Calculate real track count after throwing away old tracks. */
1442 cur_idx = track_ridx; 1442 cur_idx = track_ridx;
1443 for (i = 0; i < track_count; i++) { 1443 for (i = 0; i < track_count; i++) {
1444 if (cur_idx == track_widx) 1444 if (cur_idx == track_widx)
1445 break ; 1445 break ;
1446 1446
1447 if (++cur_idx >= MAX_TRACK) 1447 if (++cur_idx >= MAX_TRACK)
1448 cur_idx = 0; 1448 cur_idx = 0;
1449 } 1449 }
1450 1450
1451 track_count = i; 1451 track_count = i;
1452 if (tracks[track_widx].filesize == 0) { 1452 if (tracks[track_widx].filesize == 0) {
1453 if (--track_widx < 0) 1453 if (--track_widx < 0)
@@ -1467,11 +1467,11 @@ static void audio_check_buffer(void)
1467 || !queue_empty(&audio_queue) || !playing || ci.stop_codec 1467 || !queue_empty(&audio_queue) || !playing || ci.stop_codec
1468 || ci.reload_codec || playlist_end) && !filling) 1468 || ci.reload_codec || playlist_end) && !filling)
1469 return ; 1469 return ;
1470 1470
1471 mutex_lock(&mutex_bufferfill); 1471 mutex_lock(&mutex_bufferfill);
1472 initialize_buffer_fill(); 1472 initialize_buffer_fill();
1473 mutex_unlock(&mutex_bufferfill); 1473 mutex_unlock(&mutex_bufferfill);
1474 1474
1475 /* Limit buffering size at first run. */ 1475 /* Limit buffering size at first run. */
1476 if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit 1476 if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit
1477 - filebufused) { 1477 - filebufused) {
@@ -1480,17 +1480,17 @@ static void audio_check_buffer(void)
1480 else 1480 else
1481 fill_bytesleft = 0; 1481 fill_bytesleft = 0;
1482 } 1482 }
1483 1483
1484 /* Try to load remainings of the file. */ 1484 /* Try to load remainings of the file. */
1485 if (tracks[track_widx].filerem > 0) 1485 if (tracks[track_widx].filerem > 0)
1486 audio_fill_file_buffer(); 1486 audio_fill_file_buffer();
1487 1487
1488 /* Increase track write index as necessary. */ 1488 /* Increase track write index as necessary. */
1489 if (tracks[track_widx].filerem == 0 && tracks[track_widx].filesize != 0) { 1489 if (tracks[track_widx].filerem == 0 && tracks[track_widx].filesize != 0) {
1490 if (++track_widx == MAX_TRACK) 1490 if (++track_widx == MAX_TRACK)
1491 track_widx = 0; 1491 track_widx = 0;
1492 } 1492 }
1493 1493
1494 /* Load new files to fill the entire buffer. */ 1494 /* Load new files to fill the entire buffer. */
1495 if (audio_load_track(0, false, last_peek_offset + 1)) { 1495 if (audio_load_track(0, false, last_peek_offset + 1)) {
1496 if (conf_bufferlimit) 1496 if (conf_bufferlimit)
@@ -1503,13 +1503,13 @@ static void audio_check_buffer(void)
1503 { 1503 {
1504 /* Read next unbuffered track's metadata as necessary. */ 1504 /* Read next unbuffered track's metadata as necessary. */
1505 read_next_metadata(); 1505 read_next_metadata();
1506 1506
1507 generate_postbuffer_events(); 1507 generate_postbuffer_events();
1508 filling = false; 1508 filling = false;
1509 conf_bufferlimit = 0; 1509 conf_bufferlimit = 0;
1510 pcmbuf_set_boost_mode(false); 1510 pcmbuf_set_boost_mode(false);
1511 1511
1512#ifndef SIMULATOR 1512#ifndef SIMULATOR
1513 if (playing) 1513 if (playing)
1514 ata_sleep(); 1514 ata_sleep();
1515#endif 1515#endif
@@ -1533,11 +1533,12 @@ static void audio_update_trackinfo(void)
1533 codec_track_changed(); 1533 codec_track_changed();
1534 } 1534 }
1535 1535
1536 /* Automatic track change with crossfade. */ 1536 /* Automatic track change with crossfade, if not in "Track Skip Only" mode. */
1537 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()) 1537 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1538 && global_settings.crossfade != 2)
1538 { 1539 {
1539 pcmbuf_crossfade_init(false); 1540 pcmbuf_crossfade_init(false);
1540 codec_track_changed(); 1541 codec_track_changed();
1541 } 1542 }
1542 1543
1543 /* Gapless playback. */ 1544 /* Gapless playback. */
@@ -1560,7 +1561,7 @@ static int skip_next_track(bool inside_codec_thread)
1560 /* Manual track skipping. */ 1561 /* Manual track skipping. */
1561 if (new_track > 0) 1562 if (new_track > 0)
1562 last_peek_offset--; 1563 last_peek_offset--;
1563 1564
1564 /* Automatic track skipping. */ 1565 /* Automatic track skipping. */
1565 else 1566 else
1566 { 1567 {
@@ -1571,10 +1572,10 @@ static int skip_next_track(bool inside_codec_thread)
1571 last_peek_offset--; 1572 last_peek_offset--;
1572 playlist_next(1); 1573 playlist_next(1);
1573 } 1574 }
1574 1575
1575 if (++track_ridx >= MAX_TRACK) 1576 if (++track_ridx >= MAX_TRACK)
1576 track_ridx = 0; 1577 track_ridx = 0;
1577 1578
1578 /* Wait for new track data. */ 1579 /* Wait for new track data. */
1579 while (tracks[track_ridx].filesize == 0 && filling 1580 while (tracks[track_ridx].filesize == 0 && filling
1580 && !ci.stop_codec) 1581 && !ci.stop_codec)
@@ -1594,24 +1595,24 @@ static int skip_next_track(bool inside_codec_thread)
1594 } 1595 }
1595 else if (pcmbuf_is_crossfade_enabled()) 1596 else if (pcmbuf_is_crossfade_enabled())
1596 pcmbuf_crossfade_init(new_track != 0); 1597 pcmbuf_crossfade_init(new_track != 0);
1597 1598
1598 queue_post(&audio_queue, Q_AUDIO_PLAY, 0); 1599 queue_post(&audio_queue, Q_AUDIO_PLAY, 0);
1599 return SKIP_OK_DISK; 1600 return SKIP_OK_DISK;
1600 } 1601 }
1601 1602
1602 buf_ridx += cur_ti->available; 1603 buf_ridx += cur_ti->available;
1603 filebufused -= cur_ti->available; 1604 filebufused -= cur_ti->available;
1604 1605
1605 cur_ti = &tracks[track_ridx]; 1606 cur_ti = &tracks[track_ridx];
1606 buf_ridx += cur_ti->codecsize; 1607 buf_ridx += cur_ti->codecsize;
1607 filebufused -= cur_ti->codecsize; 1608 filebufused -= cur_ti->codecsize;
1608 if (buf_ridx >= filebuflen) 1609 if (buf_ridx >= filebuflen)
1609 buf_ridx -= filebuflen; 1610 buf_ridx -= filebuflen;
1610 audio_update_trackinfo(); 1611 audio_update_trackinfo();
1611 1612
1612 if (!filling) 1613 if (!filling)
1613 pcmbuf_set_boost_mode(false); 1614 pcmbuf_set_boost_mode(false);
1614 1615
1615 return SKIP_OK_RAM; 1616 return SKIP_OK_RAM;
1616} 1617}
1617 1618
@@ -1621,8 +1622,8 @@ static int skip_previous_track(bool inside_codec_thread)
1621 last_peek_offset++; 1622 last_peek_offset++;
1622 if (--track_ridx < 0) 1623 if (--track_ridx < 0)
1623 track_ridx += MAX_TRACK; 1624 track_ridx += MAX_TRACK;
1624 1625
1625 if (tracks[track_ridx].filesize == 0 || 1626 if (tracks[track_ridx].filesize == 0 ||
1626 filebufused+ci.curpos+tracks[track_ridx].filesize 1627 filebufused+ci.curpos+tracks[track_ridx].filesize
1627 /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) { 1628 /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) {
1628 logf("Loading from disk..."); 1629 logf("Loading from disk...");
@@ -1635,24 +1636,24 @@ static int skip_previous_track(bool inside_codec_thread)
1635 pcmbuf_play_stop(); 1636 pcmbuf_play_stop();
1636 else 1637 else
1637 stop_codec_flush(); 1638 stop_codec_flush();
1638 1639
1639 queue_post(&audio_queue, Q_AUDIO_PLAY, 0); 1640 queue_post(&audio_queue, Q_AUDIO_PLAY, 0);
1640 return SKIP_OK_DISK; 1641 return SKIP_OK_DISK;
1641 } 1642 }
1642 1643
1643 buf_ridx -= ci.curpos + cur_ti->codecsize; 1644 buf_ridx -= ci.curpos + cur_ti->codecsize;
1644 filebufused += ci.curpos + cur_ti->codecsize; 1645 filebufused += ci.curpos + cur_ti->codecsize;
1645 cur_ti->available = cur_ti->filesize - cur_ti->filerem; 1646 cur_ti->available = cur_ti->filesize - cur_ti->filerem;
1646 1647
1647 cur_ti = &tracks[track_ridx]; 1648 cur_ti = &tracks[track_ridx];
1648 filebufused += cur_ti->filesize; 1649 filebufused += cur_ti->filesize;
1649 cur_ti->available = cur_ti->filesize; 1650 cur_ti->available = cur_ti->filesize;
1650 if (buf_ridx < cur_ti->filesize) 1651 if (buf_ridx < cur_ti->filesize)
1651 buf_ridx += filebuflen; 1652 buf_ridx += filebuflen;
1652 buf_ridx -= cur_ti->filesize; 1653 buf_ridx -= cur_ti->filesize;
1653 1654
1654 audio_update_trackinfo(); 1655 audio_update_trackinfo();
1655 1656
1656 return SKIP_OK_RAM; 1657 return SKIP_OK_RAM;
1657} 1658}
1658 1659
@@ -1672,7 +1673,7 @@ static void audio_change_track(void)
1672 return ; 1673 return ;
1673 } 1674 }
1674 } 1675 }
1675 1676
1676 ci.reload_codec = false; 1677 ci.reload_codec = false;
1677 /* Needed for fast skipping. */ 1678 /* Needed for fast skipping. */
1678 if (cur_ti->codecsize > 0) 1679 if (cur_ti->codecsize > 0)
@@ -1692,11 +1693,11 @@ bool codec_request_next_track_callback(void)
1692 1693
1693 if (ci.stop_codec || !playing) 1694 if (ci.stop_codec || !playing)
1694 return false; 1695 return false;
1695 1696
1696#ifdef AB_REPEAT_ENABLE 1697#ifdef AB_REPEAT_ENABLE
1697 ab_end_of_track_report(); 1698 ab_end_of_track_report();
1698#endif 1699#endif
1699 1700
1700 if (!new_track) 1701 if (!new_track)
1701 pcmbuf_set_position_callback(pcmbuf_position_callback); 1702 pcmbuf_set_position_callback(pcmbuf_position_callback);
1702 1703
@@ -1707,25 +1708,25 @@ bool codec_request_next_track_callback(void)
1707 if (skip_next_track(true) != SKIP_OK_RAM) 1708 if (skip_next_track(true) != SKIP_OK_RAM)
1708 return false; 1709 return false;
1709 } 1710 }
1710 1711
1711 /* Advance to previous track. */ 1712 /* Advance to previous track. */
1712 else { 1713 else {
1713 if (skip_previous_track(true) != SKIP_OK_RAM) 1714 if (skip_previous_track(true) != SKIP_OK_RAM)
1714 return false; 1715 return false;
1715 } 1716 }
1716 1717
1717 new_track = 0; 1718 new_track = 0;
1718 ci.reload_codec = false; 1719 ci.reload_codec = false;
1719 1720
1720 logf("On-the-fly change"); 1721 logf("On-the-fly change");
1721 1722
1722 /* Check if the next codec is the same file. */ 1723 /* Check if the next codec is the same file. */
1723 if (get_codec_base_type(prev_ti->id3.codectype) != 1724 if (get_codec_base_type(prev_ti->id3.codectype) !=
1724 get_codec_base_type(cur_ti->id3.codectype)) 1725 get_codec_base_type(cur_ti->id3.codectype))
1725 { 1726 {
1726 logf("New codec:%d/%d", cur_ti->id3.codectype, 1727 logf("New codec:%d/%d", cur_ti->id3.codectype,
1727 tracks[track_ridx].id3.codectype); 1728 tracks[track_ridx].id3.codectype);
1728 1729
1729 if (cur_ti->codecsize == 0) 1730 if (cur_ti->codecsize == 0)
1730 { 1731 {
1731 logf("Loading from disk [2]..."); 1732 logf("Loading from disk [2]...");
@@ -1733,11 +1734,11 @@ bool codec_request_next_track_callback(void)
1733 } 1734 }
1734 else 1735 else
1735 ci.reload_codec = true; 1736 ci.reload_codec = true;
1736 1737
1737 return false; 1738 return false;
1738 } 1739 }
1739 1740
1740 return true; 1741 return true;
1741} 1742}
1742 1743
1743/* Invalidates all but currently playing track. */ 1744/* Invalidates all but currently playing track. */
@@ -1749,7 +1750,7 @@ void audio_invalidate_tracks(void)
1749 /* queue_post(&audio_queue, Q_AUDIO_PLAY, 0); */ 1750 /* queue_post(&audio_queue, Q_AUDIO_PLAY, 0); */
1750 return ; 1751 return ;
1751 } 1752 }
1752 1753
1753 playlist_end = false; 1754 playlist_end = false;
1754 track_count = 1; 1755 track_count = 1;
1755 last_peek_offset = 0; 1756 last_peek_offset = 0;
@@ -1799,7 +1800,7 @@ void audio_thread(void)
1799 1800
1800 /* At first initialize audio system in background. */ 1801 /* At first initialize audio system in background. */
1801 playback_init(); 1802 playback_init();
1802 1803
1803 while (1) { 1804 while (1) {
1804 if (!play_pending && queue_empty(&audio_queue)) 1805 if (!play_pending && queue_empty(&audio_queue))
1805 { 1806 {
@@ -1811,14 +1812,14 @@ void audio_thread(void)
1811 // ata_spin(); 1812 // ata_spin();
1812 sleep(1); 1813 sleep(1);
1813 } 1814 }
1814 1815
1815 queue_wait_w_tmo(&audio_queue, &ev, 0); 1816 queue_wait_w_tmo(&audio_queue, &ev, 0);
1816 if (ev.id == SYS_TIMEOUT && play_pending) 1817 if (ev.id == SYS_TIMEOUT && play_pending)
1817 { 1818 {
1818 ev.id = Q_AUDIO_PLAY; 1819 ev.id = Q_AUDIO_PLAY;
1819 ev.data = (bool *)1; 1820 ev.data = (bool *)1;
1820 } 1821 }
1821 1822
1822 switch (ev.id) { 1823 switch (ev.id) {
1823 case Q_AUDIO_PLAY: 1824 case Q_AUDIO_PLAY:
1824 /* Don't start playing immediately if user is skipping tracks 1825 /* Don't start playing immediately if user is skipping tracks
@@ -1834,7 +1835,7 @@ void audio_thread(void)
1834 } 1835 }
1835 play_pending = false; 1836 play_pending = false;
1836 last_tick = current_tick; 1837 last_tick = current_tick;
1837 1838
1838 /* Do not start crossfading if audio is paused. */ 1839 /* Do not start crossfading if audio is paused. */
1839 if (pcm_is_paused()) 1840 if (pcm_is_paused())
1840 pcmbuf_play_stop(); 1841 pcmbuf_play_stop();
@@ -1845,7 +1846,7 @@ void audio_thread(void)
1845 radio_stop(); 1846 radio_stop();
1846 } 1847 }
1847#endif 1848#endif
1848 1849
1849 logf("starting..."); 1850 logf("starting...");
1850 playing = true; 1851 playing = true;
1851 ci.stop_codec = true; 1852 ci.stop_codec = true;
@@ -1854,7 +1855,7 @@ void audio_thread(void)
1854 1855
1855 while (audio_codec_loaded) 1856 while (audio_codec_loaded)
1856 yield(); 1857 yield();
1857 1858
1858 audio_play_start((long)ev.data); 1859 audio_play_start((long)ev.data);
1859 playlist_update_resume_info(audio_current_track()); 1860 playlist_update_resume_info(audio_current_track());
1860 1861
@@ -1865,35 +1866,35 @@ void audio_thread(void)
1865 audio_stop_playback(false); 1866 audio_stop_playback(false);
1866 } 1867 }
1867 break ; 1868 break ;
1868 1869
1869 case Q_AUDIO_STOP: 1870 case Q_AUDIO_STOP:
1870 audio_stop_playback(true); 1871 audio_stop_playback(true);
1871 break ; 1872 break ;
1872 1873
1873 case Q_AUDIO_PAUSE: 1874 case Q_AUDIO_PAUSE:
1874 logf("audio_pause"); 1875 logf("audio_pause");
1875 pcmbuf_pause(true); 1876 pcmbuf_pause(true);
1876 break ; 1877 break ;
1877 1878
1878 case Q_AUDIO_RESUME: 1879 case Q_AUDIO_RESUME:
1879 logf("audio_resume"); 1880 logf("audio_resume");
1880 pcmbuf_pause(false); 1881 pcmbuf_pause(false);
1881 break ; 1882 break ;
1882 1883
1883 case Q_AUDIO_NEXT: 1884 case Q_AUDIO_NEXT:
1884 logf("audio_next"); 1885 logf("audio_next");
1885 last_tick = current_tick; 1886 last_tick = current_tick;
1886 playlist_end = false; 1887 playlist_end = false;
1887 initiate_track_change(1); 1888 initiate_track_change(1);
1888 break ; 1889 break ;
1889 1890
1890 case Q_AUDIO_PREV: 1891 case Q_AUDIO_PREV:
1891 logf("audio_prev"); 1892 logf("audio_prev");
1892 last_tick = current_tick; 1893 last_tick = current_tick;
1893 playlist_end = false; 1894 playlist_end = false;
1894 initiate_track_change(-1); 1895 initiate_track_change(-1);
1895 break; 1896 break;
1896 1897
1897 case Q_AUDIO_FF_REWIND: 1898 case Q_AUDIO_FF_REWIND:
1898 if (!playing) 1899 if (!playing)
1899 break ; 1900 break ;
@@ -1914,7 +1915,7 @@ void audio_thread(void)
1914 pcmbuf_beep(5000, 100, 2500*global_settings.beep); 1915 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
1915 initiate_dir_change(1); 1916 initiate_dir_change(1);
1916 break; 1917 break;
1917 1918
1918 case Q_AUDIO_DIR_PREV: 1919 case Q_AUDIO_DIR_PREV:
1919 logf("audio_dir_prev"); 1920 logf("audio_dir_prev");
1920 playlist_end = false; 1921 playlist_end = false;
@@ -1926,14 +1927,14 @@ void audio_thread(void)
1926 case Q_AUDIO_FLUSH: 1927 case Q_AUDIO_FLUSH:
1927 audio_invalidate_tracks(); 1928 audio_invalidate_tracks();
1928 break ; 1929 break ;
1929 1930
1930 case Q_AUDIO_TRACK_CHANGED: 1931 case Q_AUDIO_TRACK_CHANGED:
1931 if (track_changed_callback) 1932 if (track_changed_callback)
1932 track_changed_callback(&cur_ti->id3); 1933 track_changed_callback(&cur_ti->id3);
1933 playlist_update_resume_info(audio_current_track()); 1934 playlist_update_resume_info(audio_current_track());
1934 pcmbuf_set_position_callback(NULL); 1935 pcmbuf_set_position_callback(NULL);
1935 break ; 1936 break ;
1936 1937
1937 case Q_AUDIO_CODEC_DONE: 1938 case Q_AUDIO_CODEC_DONE:
1938 break ; 1939 break ;
1939 1940
@@ -1957,12 +1958,12 @@ void codec_thread(void)
1957 long codecsize; 1958 long codecsize;
1958 int status; 1959 int status;
1959 int wrap; 1960 int wrap;
1960 1961
1961 while (1) { 1962 while (1) {
1962 status = 0; 1963 status = 0;
1963 queue_wait(&codec_queue, &ev); 1964 queue_wait(&codec_queue, &ev);
1964 new_track = 0; 1965 new_track = 0;
1965 1966
1966 switch (ev.id) { 1967 switch (ev.id) {
1967 case Q_CODEC_LOAD_DISK: 1968 case Q_CODEC_LOAD_DISK:
1968 ci.stop_codec = false; 1969 ci.stop_codec = false;
@@ -1972,7 +1973,7 @@ void codec_thread(void)
1972 status = codec_load_file((char *)ev.data, &ci); 1973 status = codec_load_file((char *)ev.data, &ci);
1973 mutex_unlock(&mutex_codecthread); 1974 mutex_unlock(&mutex_codecthread);
1974 break ; 1975 break ;
1975 1976
1976 case Q_CODEC_LOAD: 1977 case Q_CODEC_LOAD:
1977 logf("Codec start"); 1978 logf("Codec start");
1978 codecsize = cur_ti->codecsize; 1979 codecsize = cur_ti->codecsize;
@@ -1984,7 +1985,7 @@ void codec_thread(void)
1984 audio_stop_playback(true); 1985 audio_stop_playback(true);
1985 break ; 1986 break ;
1986 } 1987 }
1987 1988
1988 ci.stop_codec = false; 1989 ci.stop_codec = false;
1989 wrap = (long)&filebuf[filebuflen] - (long)cur_ti->codecbuf; 1990 wrap = (long)&filebuf[filebuflen] - (long)cur_ti->codecbuf;
1990 audio_codec_loaded = true; 1991 audio_codec_loaded = true;
@@ -1995,7 +1996,7 @@ void codec_thread(void)
1995 mutex_unlock(&mutex_codecthread); 1996 mutex_unlock(&mutex_codecthread);
1996 break ; 1997 break ;
1997 1998
1998#ifndef SIMULATOR 1999#ifndef SIMULATOR
1999 case SYS_USB_CONNECTED: 2000 case SYS_USB_CONNECTED:
2000 while (voice_codec_loaded) { 2001 while (voice_codec_loaded) {
2001 if (current_codec != CODEC_IDX_VOICE) 2002 if (current_codec != CODEC_IDX_VOICE)
@@ -2010,7 +2011,7 @@ void codec_thread(void)
2010 } 2011 }
2011 2012
2012 audio_codec_loaded = false; 2013 audio_codec_loaded = false;
2013 2014
2014 switch (ev.id) { 2015 switch (ev.id) {
2015 case Q_CODEC_LOAD_DISK: 2016 case Q_CODEC_LOAD_DISK:
2016 case Q_CODEC_LOAD: 2017 case Q_CODEC_LOAD:
@@ -2022,10 +2023,10 @@ void codec_thread(void)
2022 } else { 2023 } else {
2023 logf("Codec finished"); 2024 logf("Codec finished");
2024 } 2025 }
2025 2026
2026 if (playing && !ci.stop_codec) 2027 if (playing && !ci.stop_codec)
2027 audio_change_track(); 2028 audio_change_track();
2028 2029
2029 // queue_post(&audio_queue, Q_AUDIO_CODEC_DONE, (void *)status); 2030 // queue_post(&audio_queue, Q_AUDIO_CODEC_DONE, (void *)status);
2030 } 2031 }
2031 } 2032 }
@@ -2036,8 +2037,8 @@ static void reset_buffer(void)
2036 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; 2037 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE];
2037 filebuflen = audiobufend - audiobuf - MALLOC_BUFSIZE - GUARD_BUFSIZE - 2038 filebuflen = audiobufend - audiobuf - MALLOC_BUFSIZE - GUARD_BUFSIZE -
2038 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_FADE_CHUNK); 2039 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_FADE_CHUNK);
2039 2040
2040 2041
2041 if (talk_get_bufsize() && voice_codec_loaded) 2042 if (talk_get_bufsize() && voice_codec_loaded)
2042 { 2043 {
2043 filebuf = &filebuf[talk_get_bufsize()]; 2044 filebuf = &filebuf[talk_get_bufsize()];
@@ -2077,9 +2078,9 @@ void voice_codec_thread(void)
2077 voice_codec_loaded = true; 2078 voice_codec_loaded = true;
2078 reset_buffer(); 2079 reset_buffer();
2079 ci_voice.stop_codec = false; 2080 ci_voice.stop_codec = false;
2080 2081
2081 status = codec_load_file((char *)ev.data, &ci_voice); 2082 status = codec_load_file((char *)ev.data, &ci_voice);
2082 2083
2083 logf("Voice codec finished"); 2084 logf("Voice codec finished");
2084 audio_stop_playback(true); 2085 audio_stop_playback(true);
2085 mutex_unlock(&mutex_codecthread); 2086 mutex_unlock(&mutex_codecthread);
@@ -2088,7 +2089,7 @@ void voice_codec_thread(void)
2088 reset_buffer(); 2089 reset_buffer();
2089 break ; 2090 break ;
2090 2091
2091#ifndef SIMULATOR 2092#ifndef SIMULATOR
2092 case SYS_USB_CONNECTED: 2093 case SYS_USB_CONNECTED:
2093 logf("USB: Voice codec"); 2094 logf("USB: Voice codec");
2094 usb_acknowledge(SYS_USB_CONNECTED_ACK); 2095 usb_acknowledge(SYS_USB_CONNECTED_ACK);
@@ -2113,7 +2114,7 @@ void voice_init(void)
2113 2114
2114 if (!talk_get_bufsize()) 2115 if (!talk_get_bufsize())
2115 return ; 2116 return ;
2116 2117
2117 logf("Starting voice codec"); 2118 logf("Starting voice codec");
2118 queue_post(&voice_codec_queue, Q_CODEC_LOAD_DISK, (void *)CODEC_MPA_L3); 2119 queue_post(&voice_codec_queue, Q_CODEC_LOAD_DISK, (void *)CODEC_MPA_L3);
2119 while (!voice_codec_loaded) 2120 while (!voice_codec_loaded)
@@ -2125,19 +2126,19 @@ struct mp3entry* audio_current_track(void)
2125 const char *filename; 2126 const char *filename;
2126 const char *p; 2127 const char *p;
2127 static struct mp3entry temp_id3; 2128 static struct mp3entry temp_id3;
2128 2129
2129 if (track_count > 0 && cur_ti->taginfo_ready) 2130 if (track_count > 0 && cur_ti->taginfo_ready)
2130 return (struct mp3entry *)&cur_ti->id3; 2131 return (struct mp3entry *)&cur_ti->id3;
2131 2132
2132 filename = playlist_peek(0); 2133 filename = playlist_peek(0);
2133 if (!filename) 2134 if (!filename)
2134 filename = "No file!"; 2135 filename = "No file!";
2135 2136
2136#ifdef HAVE_TC_RAMCACHE 2137#ifdef HAVE_TC_RAMCACHE
2137 if (tagcache_fill_tags(&temp_id3, filename)) 2138 if (tagcache_fill_tags(&temp_id3, filename))
2138 return &temp_id3; 2139 return &temp_id3;
2139#endif 2140#endif
2140 2141
2141 p = strrchr(filename, '/'); 2142 p = strrchr(filename, '/');
2142 if (!p) 2143 if (!p)
2143 p = filename; 2144 p = filename;
@@ -2154,16 +2155,16 @@ struct mp3entry* audio_current_track(void)
2154struct mp3entry* audio_next_track(void) 2155struct mp3entry* audio_next_track(void)
2155{ 2156{
2156 int next_idx = track_ridx + 1; 2157 int next_idx = track_ridx + 1;
2157 2158
2158 if (track_count == 0) 2159 if (track_count == 0)
2159 return NULL; 2160 return NULL;
2160 2161
2161 if (next_idx >= MAX_TRACK) 2162 if (next_idx >= MAX_TRACK)
2162 next_idx = 0; 2163 next_idx = 0;
2163 2164
2164 if (!tracks[next_idx].taginfo_ready) 2165 if (!tracks[next_idx].taginfo_ready)
2165 return NULL; 2166 return NULL;
2166 2167
2167 return &tracks[next_idx].id3; 2168 return &tracks[next_idx].id3;
2168} 2169}
2169 2170
@@ -2173,7 +2174,7 @@ bool audio_has_changed_track(void)
2173 track_changed = false; 2174 track_changed = false;
2174 return true; 2175 return true;
2175 } 2176 }
2176 2177
2177 return false; 2178 return false;
2178} 2179}
2179 2180
@@ -2191,7 +2192,7 @@ void audio_play(long offset)
2191 stop_codec_flush(); 2192 stop_codec_flush();
2192 pcmbuf_play_stop(); 2193 pcmbuf_play_stop();
2193 } 2194 }
2194 2195
2195 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset); 2196 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
2196} 2197}
2197 2198
@@ -2228,11 +2229,11 @@ void audio_next(void)
2228 return ; 2229 return ;
2229 playlist_next(1); 2230 playlist_next(1);
2230 track_changed = true; 2231 track_changed = true;
2231 2232
2232 /* Force WPS to update even if audio thread is blocked spinning. */ 2233 /* Force WPS to update even if audio thread is blocked spinning. */
2233 if (mutex_bufferfill.locked) 2234 if (mutex_bufferfill.locked)
2234 cur_ti->taginfo_ready = false; 2235 cur_ti->taginfo_ready = false;
2235 2236
2236 queue_post(&audio_queue, Q_AUDIO_NEXT, 0); 2237 queue_post(&audio_queue, Q_AUDIO_NEXT, 0);
2237} 2238}
2238 2239
@@ -2246,11 +2247,11 @@ void audio_prev(void)
2246 return ; 2247 return ;
2247 playlist_next(-1); 2248 playlist_next(-1);
2248 track_changed = true; 2249 track_changed = true;
2249 2250
2250 /* Force WPS to update even if audio thread is blocked spinning. */ 2251 /* Force WPS to update even if audio thread is blocked spinning. */
2251 if (mutex_bufferfill.locked) 2252 if (mutex_bufferfill.locked)
2252 cur_ti->taginfo_ready = false; 2253 cur_ti->taginfo_ready = false;
2253 2254
2254 queue_post(&audio_queue, Q_AUDIO_PREV, 0); 2255 queue_post(&audio_queue, Q_AUDIO_PREV, 0);
2255} 2256}
2256 2257
@@ -2289,13 +2290,13 @@ void audio_error_clear(void)
2289int audio_status(void) 2290int audio_status(void)
2290{ 2291{
2291 int ret = 0; 2292 int ret = 0;
2292 2293
2293 if (playing) 2294 if (playing)
2294 ret |= AUDIO_STATUS_PLAY; 2295 ret |= AUDIO_STATUS_PLAY;
2295 2296
2296 if (pcm_is_paused()) 2297 if (pcm_is_paused())
2297 ret |= AUDIO_STATUS_PAUSE; 2298 ret |= AUDIO_STATUS_PAUSE;
2298 2299
2299 return ret; 2300 return ret;
2300} 2301}
2301 2302
@@ -2322,7 +2323,7 @@ static void mp3_set_elapsed(struct mp3entry* id3)
2322 break; 2323 break;
2323 } 2324 }
2324 } 2325 }
2325 2326
2326 i--; 2327 i--;
2327 if (i < 0) 2328 if (i < 0)
2328 i = 0; 2329 i = 0;
@@ -2335,7 +2336,7 @@ static void mp3_set_elapsed(struct mp3entry* id3)
2335 } 2336 }
2336 else 2337 else
2337 { 2338 {
2338 nextpos = 256; 2339 nextpos = 256;
2339 } 2340 }
2340 2341
2341 remainder = id3->offset - (relpos * (id3->filesize / 256)); 2342 remainder = id3->offset - (relpos * (id3->filesize / 256));
@@ -2366,7 +2367,7 @@ int mp3_get_file_pos(void)
2366{ 2367{
2367 int pos = -1; 2368 int pos = -1;
2368 struct mp3entry *id3 = audio_current_track(); 2369 struct mp3entry *id3 = audio_current_track();
2369 2370
2370 if (id3->vbr) 2371 if (id3->vbr)
2371 { 2372 {
2372 if (id3->has_toc) 2373 if (id3->has_toc)
@@ -2374,20 +2375,20 @@ int mp3_get_file_pos(void)
2374 /* Use the TOC to find the new position */ 2375 /* Use the TOC to find the new position */
2375 unsigned int percent, remainder; 2376 unsigned int percent, remainder;
2376 int curtoc, nexttoc, plen; 2377 int curtoc, nexttoc, plen;
2377 2378
2378 percent = (id3->elapsed*100)/id3->length; 2379 percent = (id3->elapsed*100)/id3->length;
2379 if (percent > 99) 2380 if (percent > 99)
2380 percent = 99; 2381 percent = 99;
2381 2382
2382 curtoc = id3->toc[percent]; 2383 curtoc = id3->toc[percent];
2383 2384
2384 if (percent < 99) 2385 if (percent < 99)
2385 nexttoc = id3->toc[percent+1]; 2386 nexttoc = id3->toc[percent+1];
2386 else 2387 else
2387 nexttoc = 256; 2388 nexttoc = 256;
2388 2389
2389 pos = (id3->filesize/256)*curtoc; 2390 pos = (id3->filesize/256)*curtoc;
2390 2391
2391 /* Use the remainder to get a more accurate position */ 2392 /* Use the remainder to get a more accurate position */
2392 remainder = (id3->elapsed*100)%id3->length; 2393 remainder = (id3->elapsed*100)%id3->length;
2393 remainder = (remainder*100)/id3->length; 2394 remainder = (remainder*100)/id3->length;
@@ -2419,7 +2420,7 @@ int mp3_get_file_pos(void)
2419 /* skip past id3v2 tag and other leading garbage */ 2420 /* skip past id3v2 tag and other leading garbage */
2420 pos = id3->first_frame_offset; 2421 pos = id3->first_frame_offset;
2421 } 2422 }
2422 return pos; 2423 return pos;
2423} 2424}
2424 2425
2425void mp3_play_data(const unsigned char* start, int size, 2426void mp3_play_data(const unsigned char* start, int size,
@@ -2460,7 +2461,7 @@ void audio_set_crossfade(int enable)
2460 seconds = global_settings.crossfade_fade_out_delay 2461 seconds = global_settings.crossfade_fade_out_delay
2461 + global_settings.crossfade_fade_out_duration; 2462 + global_settings.crossfade_fade_out_duration;
2462 } 2463 }
2463 2464
2464 /* Buffer has to be at least 2s long. */ 2465 /* Buffer has to be at least 2s long. */
2465 seconds += 2; 2466 seconds += 2;
2466 logf("buf len: %d", seconds); 2467 logf("buf len: %d", seconds);
@@ -2481,7 +2482,7 @@ void audio_set_crossfade(int enable)
2481 logf("fbuf:%dB", filebuflen); 2482 logf("fbuf:%dB", filebuflen);
2482 2483
2483 voice_init(); 2484 voice_init();
2484 2485
2485 /* Restart playback. */ 2486 /* Restart playback. */
2486 if (was_playing) { 2487 if (was_playing) {
2487 audio_play(offset); 2488 audio_play(offset);
@@ -2503,7 +2504,7 @@ void test_buffer_event(struct mp3entry *id3, bool last_track)
2503{ 2504{
2504 (void)id3; 2505 (void)id3;
2505 (void)last_track; 2506 (void)last_track;
2506 2507
2507 logf("be:%d%s", last_track, id3->path); 2508 logf("be:%d%s", last_track, id3->path);
2508} 2509}
2509 2510
@@ -2511,7 +2512,7 @@ void test_unbuffer_event(struct mp3entry *id3, bool last_track)
2511{ 2512{
2512 (void)id3; 2513 (void)id3;
2513 (void)last_track; 2514 (void)last_track;
2514 2515
2515 logf("ube:%d%s", last_track, id3->path); 2516 logf("ube:%d%s", last_track, id3->path);
2516} 2517}
2517 2518
@@ -2565,7 +2566,7 @@ static void playback_init(void)
2565 queue_wait(&audio_queue, &ev); 2566 queue_wait(&audio_queue, &ev);
2566 if (ev.id == Q_AUDIO_POSTINIT) 2567 if (ev.id == Q_AUDIO_POSTINIT)
2567 break ; 2568 break ;
2568 2569
2569#ifndef SIMULATOR 2570#ifndef SIMULATOR
2570 if (ev.id == SYS_USB_CONNECTED) 2571 if (ev.id == SYS_USB_CONNECTED)
2571 { 2572 {
@@ -2575,20 +2576,20 @@ static void playback_init(void)
2575 } 2576 }
2576#endif 2577#endif
2577 } 2578 }
2578 2579
2579 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; 2580 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE];
2580 2581
2581 /* Apply relevant settings */ 2582 /* Apply relevant settings */
2582 audio_set_buffer_margin(global_settings.buffer_margin); 2583 audio_set_buffer_margin(global_settings.buffer_margin);
2583 audio_set_crossfade(global_settings.crossfade); 2584 audio_set_crossfade(global_settings.crossfade);
2584 2585
2585 sound_settings_apply(); 2586 sound_settings_apply();
2586} 2587}
2587 2588
2588void audio_preinit(void) 2589void audio_preinit(void)
2589{ 2590{
2590 logf("playback system pre-init"); 2591 logf("playback system pre-init");
2591 2592
2592 filebufused = 0; 2593 filebufused = 0;
2593 filling = false; 2594 filling = false;
2594 current_codec = CODEC_IDX_AUDIO; 2595 current_codec = CODEC_IDX_AUDIO;
@@ -2602,7 +2603,7 @@ void audio_preinit(void)
2602 track_changed_callback = NULL; 2603 track_changed_callback = NULL;
2603 /* Just to prevent cur_ti never be anything random. */ 2604 /* Just to prevent cur_ti never be anything random. */
2604 cur_ti = &tracks[0]; 2605 cur_ti = &tracks[0];
2605 2606
2606 mutex_init(&mutex_bufferfill); 2607 mutex_init(&mutex_bufferfill);
2607 mutex_init(&mutex_codecthread); 2608 mutex_init(&mutex_codecthread);
2608 2609