summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
authorBrandon Low <lostlogic@rockbox.org>2006-03-24 13:43:15 +0000
committerBrandon Low <lostlogic@rockbox.org>2006-03-24 13:43:15 +0000
commit86f1e2ead283d86f6896ca0f98c0b711da5e2cfe (patch)
treefe961ef2fdfe8a5d6317604246acf63440326435 /apps/playback.c
parentb1cd32913dcd9bba7960c1f8f3b384ee1ff5a259 (diff)
downloadrockbox-86f1e2ead283d86f6896ca0f98c0b711da5e2cfe.tar.gz
rockbox-86f1e2ead283d86f6896ca0f98c0b711da5e2cfe.zip
Convert playback.c to use unsigned byte counters, and _minor_ refactoring of buffer callbacks
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9227 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c184
1 files changed, 98 insertions, 86 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 0c04057593..bf6e5bc4be 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -145,7 +145,7 @@ static struct mutex mutex_codecthread;
145static struct mp3entry id3_voice; 145static struct mp3entry id3_voice;
146 146
147static char *voicebuf; 147static char *voicebuf;
148static int voice_remaining; 148static size_t voice_remaining;
149static bool voice_is_playing; 149static bool voice_is_playing;
150static void (*voice_getmore)(unsigned char** start, int* size); 150static void (*voice_getmore)(unsigned char** start, int* size);
151 151
@@ -159,14 +159,14 @@ extern unsigned char codecbuf[];
159static char *filebuf; 159static char *filebuf;
160 160
161/* Total size of the ring buffer. */ 161/* Total size of the ring buffer. */
162int filebuflen; 162size_t filebuflen;
163 163
164/* Bytes available in the buffer. */ 164/* Bytes available in the buffer. */
165int filebufused; 165size_t filebufused;
166 166
167/* Ring buffer read and write indexes. */ 167/* Ring buffer read and write indexes. */
168static volatile int buf_ridx; 168static volatile size_t buf_ridx;
169static volatile int buf_widx; 169static volatile size_t buf_widx;
170 170
171#ifndef SIMULATOR 171#ifndef SIMULATOR
172static unsigned char *iram_buf[2]; 172static unsigned char *iram_buf[2];
@@ -187,7 +187,7 @@ static bool track_changed;
187static int current_fd; 187static int current_fd;
188 188
189/* Information about how many bytes left on the buffer re-fill run. */ 189/* Information about how many bytes left on the buffer re-fill run. */
190static long fill_bytesleft; 190static size_t fill_bytesleft;
191 191
192/* Track info structure about songs in the file buffer. */ 192/* Track info structure about songs in the file buffer. */
193static struct track_info tracks[MAX_TRACK]; 193static struct track_info tracks[MAX_TRACK];
@@ -215,10 +215,10 @@ void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track);
215static void playback_init(void); 215static void playback_init(void);
216 216
217/* Configuration */ 217/* Configuration */
218static int conf_bufferlimit; 218static size_t conf_bufferlimit;
219static int conf_watermark; 219static size_t conf_watermark;
220static int conf_filechunk; 220static size_t conf_filechunk;
221static int buffer_margin; 221static size_t buffer_margin;
222 222
223static bool v1first = false; 223static bool v1first = false;
224 224
@@ -388,7 +388,7 @@ bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
388 length); 388 length);
389} 389}
390 390
391void* get_codec_memory_callback(long *size) 391void* get_codec_memory_callback(size_t *size)
392{ 392{
393 *size = MALLOC_BUFSIZE; 393 *size = MALLOC_BUFSIZE;
394 if (voice_codec_loaded) 394 if (voice_codec_loaded)
@@ -413,7 +413,8 @@ void codec_set_elapsed_callback(unsigned int value)
413{ 413{
414 unsigned int latency; 414 unsigned int latency;
415 415
416 if (ci.stop_codec || current_codec == CODEC_IDX_VOICE) 416 /* We don't save or display offsets for voice */
417 if (current_codec == CODEC_IDX_VOICE)
417 return ; 418 return ;
418 419
419#ifdef AB_REPEAT_ENABLE 420#ifdef AB_REPEAT_ENABLE
@@ -429,11 +430,12 @@ void codec_set_elapsed_callback(unsigned int value)
429 } 430 }
430} 431}
431 432
432void codec_set_offset_callback(unsigned int value) 433void codec_set_offset_callback(size_t value)
433{ 434{
434 unsigned int latency; 435 unsigned int latency;
435 436
436 if (ci.stop_codec || current_codec == CODEC_IDX_VOICE) 437 /* We don't save or display offsets for voice */
438 if (current_codec == CODEC_IDX_VOICE)
437 return ; 439 return ;
438 440
439 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8; 441 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
@@ -445,43 +447,56 @@ void codec_set_offset_callback(unsigned int value)
445 } 447 }
446} 448}
447 449
448long codec_filebuf_callback(void *ptr, long size) 450static void advance_buffer_counters(size_t amount) {
451 buf_ridx += amount;
452 if (buf_ridx >= filebuflen)
453 buf_ridx -= filebuflen;
454 ci.curpos += amount;
455 cur_ti->available -= amount;
456 filebufused -= amount;
457}
458
459/* copy up-to size bytes into ptr and return the actual size copied */
460size_t codec_filebuf_callback(void *ptr, size_t size)
449{ 461{
450 char *buf = (char *)ptr; 462 char *buf = (char *)ptr;
451 int copy_n; 463 size_t copy_n;
452 int part_n; 464 size_t part_n;
453 465
454 if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE) 466 if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
455 return 0; 467 return 0;
456 468
457 copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem); 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) */
471 copy_n = MIN(size, cur_ti->available + cur_ti->filerem);
458 472
473 /* Nothing requested OR nothing left */
474 if (copy_n == 0)
475 return 0;
476
477 /* Let the disk buffer catch fill until enough data is available */
459 while (copy_n > cur_ti->available) { 478 while (copy_n > cur_ti->available) {
460 yield(); 479 yield();
461 if (ci.stop_codec || ci.reload_codec) 480 if (ci.stop_codec || ci.reload_codec)
462 return 0; 481 return 0;
463 } 482 }
464 483
465 if (copy_n == 0) 484 /* Copy as much as possible without wrapping */
466 return 0;
467
468 part_n = MIN(copy_n, filebuflen - buf_ridx); 485 part_n = MIN(copy_n, filebuflen - buf_ridx);
469 memcpy(buf, &filebuf[buf_ridx], part_n); 486 memcpy(buf, &filebuf[buf_ridx], part_n);
487 /* Copy the rest in the case of a wrap */
470 if (part_n < copy_n) { 488 if (part_n < copy_n) {
471 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n); 489 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
472 } 490 }
473 491
474 buf_ridx += copy_n; 492 /* Update read and other position pointers */
475 if (buf_ridx >= filebuflen) 493 advance_buffer_counters(copy_n);
476 buf_ridx -= filebuflen;
477 ci.curpos += copy_n;
478 cur_ti->available -= copy_n;
479 filebufused -= copy_n;
480 494
495 /* Return the actual amount of data copied to the buffer */
481 return copy_n; 496 return copy_n;
482} 497}
483 498
484void* voice_request_data(long *realsize, long reqsize) 499void* voice_request_data(size_t *realsize, size_t reqsize)
485{ 500{
486 while (queue_empty(&voice_codec_queue) && (voice_remaining == 0 501 while (queue_empty(&voice_codec_queue) && (voice_remaining == 0
487 || voicebuf == NULL) && !ci_voice.stop_codec) 502 || voicebuf == NULL) && !ci_voice.stop_codec)
@@ -503,10 +518,8 @@ void* voice_request_data(long *realsize, long reqsize)
503 if (voice_remaining) 518 if (voice_remaining)
504 { 519 {
505 voice_is_playing = true; 520 voice_is_playing = true;
506 break ;
507 } 521 }
508 522 else if (voice_getmore != NULL)
509 if (voice_getmore != NULL)
510 { 523 {
511 voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining); 524 voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
512 525
@@ -519,13 +532,8 @@ void* voice_request_data(long *realsize, long reqsize)
519 } 532 }
520 } 533 }
521 534
522 if (reqsize < 0)
523 reqsize = 0;
524
525 voice_is_playing = true; 535 voice_is_playing = true;
526 *realsize = voice_remaining; 536 *realsize = MIN(voice_remaining, reqsize);
527 if (*realsize > reqsize)
528 *realsize = reqsize;
529 537
530 if (*realsize == 0) 538 if (*realsize == 0)
531 return NULL; 539 return NULL;
@@ -533,9 +541,9 @@ void* voice_request_data(long *realsize, long reqsize)
533 return voicebuf; 541 return voicebuf;
534} 542}
535 543
536void* codec_request_buffer_callback(long *realsize, long reqsize) 544void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
537{ 545{
538 long part_n; 546 size_t short_n, copy_n, buf_rem;
539 547
540 /* Voice codec. */ 548 /* Voice codec. */
541 if (current_codec == CODEC_IDX_VOICE) { 549 if (current_codec == CODEC_IDX_VOICE) {
@@ -547,12 +555,13 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
547 return NULL; 555 return NULL;
548 } 556 }
549 557
550 *realsize = MIN((off_t)reqsize, (off_t)cur_ti->available + cur_ti->filerem); 558 copy_n = MIN(reqsize, cur_ti->available + cur_ti->filerem);
551 if (*realsize == 0) { 559 if (copy_n == 0) {
560 *realsize = 0;
552 return NULL; 561 return NULL;
553 } 562 }
554 563
555 while ((int)*realsize > cur_ti->available) { 564 while (copy_n > cur_ti->available) {
556 yield(); 565 yield();
557 if (ci.stop_codec || ci.reload_codec) { 566 if (ci.stop_codec || ci.reload_codec) {
558 *realsize = 0; 567 *realsize = 0;
@@ -560,19 +569,24 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
560 } 569 }
561 } 570 }
562 571
563 part_n = MIN((int)*realsize, filebuflen - buf_ridx); 572 /* How much is left at the end of the file buffer before wrap? */
564 if (part_n < *realsize) { 573 buf_rem = filebuflen - buf_ridx;
565 part_n += GUARD_BUFSIZE; 574 /* If we can't satisfy the request without wrapping */
566 if (part_n < *realsize) 575 if (buf_rem < copy_n) {
567 *realsize = part_n; 576 /* How short are we? */
568 memcpy(&filebuf[filebuflen], &filebuf[0], *realsize - 577 short_n = copy_n - buf_rem;
569 (filebuflen - buf_ridx)); 578 /* If we can fudge it with the guardbuf */
579 if (short_n < GUARD_BUFSIZE)
580 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
581 else
582 copy_n = buf_rem;
570 } 583 }
571 584
585 *realsize = copy_n;
572 return (char *)&filebuf[buf_ridx]; 586 return (char *)&filebuf[buf_ridx];
573} 587}
574 588
575static bool rebuffer_and_seek(int newpos) 589static bool rebuffer_and_seek(size_t newpos)
576{ 590{
577 int fd; 591 int fd;
578 592
@@ -613,11 +627,11 @@ static bool rebuffer_and_seek(int newpos)
613 return true; 627 return true;
614} 628}
615 629
616void codec_advance_buffer_callback(long amount) 630void codec_advance_buffer_callback(size_t amount)
617{ 631{
618 if (current_codec == CODEC_IDX_VOICE) { 632 if (current_codec == CODEC_IDX_VOICE) {
619 //logf("voice ad.buf:%d", amount); 633 //logf("voice ad.buf:%d", amount);
620 amount = MAX(0, MIN(amount, voice_remaining)); 634 amount = MIN(amount, voice_remaining);
621 voicebuf += amount; 635 voicebuf += amount;
622 voice_remaining -= amount; 636 voice_remaining -= amount;
623 637
@@ -636,23 +650,19 @@ void codec_advance_buffer_callback(long amount)
636 return ; 650 return ;
637 } 651 }
638 652
639 buf_ridx += amount; 653 advance_buffer_counters(amount);
640 if (buf_ridx >= filebuflen) 654
641 buf_ridx -= filebuflen;
642 cur_ti->available -= amount;
643 filebufused -= amount;
644 ci.curpos += amount;
645 codec_set_offset_callback(ci.curpos); 655 codec_set_offset_callback(ci.curpos);
646} 656}
647 657
648void codec_advance_buffer_loc_callback(void *ptr) 658void codec_advance_buffer_loc_callback(void *ptr)
649{ 659{
650 long amount; 660 size_t amount;
651 661
652 if (current_codec == CODEC_IDX_VOICE) 662 if (current_codec == CODEC_IDX_VOICE)
653 amount = (long)ptr - (long)voicebuf; 663 amount = (size_t)ptr - (size_t)voicebuf;
654 else 664 else
655 amount = (long)ptr - (long)&filebuf[buf_ridx]; 665 amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
656 codec_advance_buffer_callback(amount); 666 codec_advance_buffer_callback(amount);
657} 667}
658 668
@@ -672,16 +682,13 @@ void codec_seek_complete_callback(void)
672 ci.seek_time = 0; 682 ci.seek_time = 0;
673} 683}
674 684
675bool codec_seek_buffer_callback(off_t newpos) 685bool codec_seek_buffer_callback(size_t newpos)
676{ 686{
677 int difference; 687 int difference;
678 688
679 if (current_codec == CODEC_IDX_VOICE) 689 if (current_codec == CODEC_IDX_VOICE)
680 return false; 690 return false;
681 691
682 if (newpos < 0)
683 newpos = 0;
684
685 if (newpos >= cur_ti->filesize) 692 if (newpos >= cur_ti->filesize)
686 newpos = cur_ti->filesize - 1; 693 newpos = cur_ti->filesize - 1;
687 694
@@ -706,9 +713,9 @@ bool codec_seek_buffer_callback(off_t newpos)
706 logf("seek: -%d", difference); 713 logf("seek: -%d", difference);
707 filebufused += difference; 714 filebufused += difference;
708 cur_ti->available += difference; 715 cur_ti->available += difference;
716 if (buf_ridx < (unsigned)difference)
717 buf_ridx += filebuflen;
709 buf_ridx -= difference; 718 buf_ridx -= difference;
710 if (buf_ridx < 0)
711 buf_ridx = filebuflen + buf_ridx;
712 ci.curpos -= difference; 719 ci.curpos -= difference;
713 720
714 return true; 721 return true;
@@ -716,7 +723,7 @@ bool codec_seek_buffer_callback(off_t newpos)
716 723
717static void set_filebuf_watermark(int seconds) 724static void set_filebuf_watermark(int seconds)
718{ 725{
719 long bytes; 726 size_t bytes;
720 727
721 if (current_codec == CODEC_IDX_VOICE) 728 if (current_codec == CODEC_IDX_VOICE)
722 return ; 729 return ;
@@ -724,7 +731,7 @@ static void set_filebuf_watermark(int seconds)
724 if (!filebuf) 731 if (!filebuf)
725 return; /* Audio buffers not yet set up */ 732 return; /* Audio buffers not yet set up */
726 733
727 bytes = MAX((int)cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark); 734 bytes = MAX(cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
728 bytes = MIN(bytes, filebuflen / 2); 735 bytes = MIN(bytes, filebuflen / 2);
729 conf_watermark = bytes; 736 conf_watermark = bytes;
730} 737}
@@ -803,14 +810,15 @@ void strip_id3v1_tag(void)
803{ 810{
804 int i; 811 int i;
805 static const unsigned char tag[] = "TAG"; 812 static const unsigned char tag[] = "TAG";
806 int tagptr; 813 size_t tagptr;
807 bool found = true; 814 bool found = true;
808 815
809 if (filebufused >= 128) 816 if (filebufused >= 128)
810 { 817 {
811 tagptr = buf_widx - 128; 818 if (buf_widx < 128)
812 if (tagptr < 0) 819 tagptr = filebuflen + buf_widx - 128;
813 tagptr += filebuflen; 820 else
821 tagptr = buf_widx - 128;
814 822
815 for(i = 0;i < 3;i++) 823 for(i = 0;i < 3;i++)
816 { 824 {
@@ -839,7 +847,9 @@ void strip_id3v1_tag(void)
839 847
840static void audio_fill_file_buffer(void) 848static void audio_fill_file_buffer(void)
841{ 849{
842 long i, size; 850 unsigned long i;
851 size_t size;
852 size_t copy_n;
843 int rc; 853 int rc;
844 854
845 if (current_fd < 0) 855 if (current_fd < 0)
@@ -858,9 +868,9 @@ static void audio_fill_file_buffer(void)
858 868
859 if (fill_bytesleft == 0) 869 if (fill_bytesleft == 0)
860 break ; 870 break ;
861 rc = MIN(conf_filechunk, filebuflen - buf_widx); 871 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
862 rc = MIN(rc, fill_bytesleft); 872 copy_n = MIN(copy_n, fill_bytesleft);
863 rc = read(current_fd, &filebuf[buf_widx], rc); 873 rc = read(current_fd, &filebuf[buf_widx], copy_n);
864 if (rc <= 0) { 874 if (rc <= 0) {
865 tracks[track_widx].filerem = 0; 875 tracks[track_widx].filerem = 0;
866 break ; 876 break ;
@@ -901,11 +911,12 @@ static int get_codec_base_type(int type)
901 911
902static bool loadcodec(bool start_play) 912static bool loadcodec(bool start_play)
903{ 913{
904 off_t size; 914 size_t size;
905 int fd; 915 int fd;
906 int i, rc; 916 unsigned int i;
917 int rc;
907 const char *codec_path; 918 const char *codec_path;
908 int copy_n; 919 size_t copy_n;
909 int prev_track; 920 int prev_track;
910 921
911 switch (tracks[track_widx].id3.codectype) { 922 switch (tracks[track_widx].id3.codectype) {
@@ -994,7 +1005,7 @@ static bool loadcodec(bool start_play)
994 } 1005 }
995 1006
996 size = filesize(fd); 1007 size = filesize(fd);
997 if ((off_t)fill_bytesleft < size + conf_watermark) { 1008 if (fill_bytesleft < size + conf_watermark) {
998 logf("Not enough space"); 1009 logf("Not enough space");
999 /* Set codectype back to zero to indicate no codec was loaded. */ 1010 /* Set codectype back to zero to indicate no codec was loaded. */
1000 tracks[track_widx].id3.codectype = 0; 1011 tracks[track_widx].id3.codectype = 0;
@@ -1464,7 +1475,10 @@ static void audio_check_buffer(void)
1464 /* Limit buffering size at first run. */ 1475 /* Limit buffering size at first run. */
1465 if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit 1476 if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit
1466 - filebufused) { 1477 - filebufused) {
1467 fill_bytesleft = MAX(0, conf_bufferlimit - filebufused); 1478 if (conf_bufferlimit > filebufused)
1479 fill_bytesleft = conf_bufferlimit - filebufused;
1480 else
1481 fill_bytesleft = 0;
1468 } 1482 }
1469 1483
1470 /* Try to load remainings of the file. */ 1484 /* Try to load remainings of the file. */
@@ -1631,11 +1645,11 @@ static int skip_previous_track(bool inside_codec_thread)
1631 cur_ti->available = cur_ti->filesize - cur_ti->filerem; 1645 cur_ti->available = cur_ti->filesize - cur_ti->filerem;
1632 1646
1633 cur_ti = &tracks[track_ridx]; 1647 cur_ti = &tracks[track_ridx];
1634 buf_ridx -= cur_ti->filesize;
1635 filebufused += cur_ti->filesize; 1648 filebufused += cur_ti->filesize;
1636 cur_ti->available = cur_ti->filesize; 1649 cur_ti->available = cur_ti->filesize;
1637 if (buf_ridx < 0) 1650 if (buf_ridx < cur_ti->filesize)
1638 buf_ridx += filebuflen; 1651 buf_ridx += filebuflen;
1652 buf_ridx -= cur_ti->filesize;
1639 1653
1640 audio_update_trackinfo(); 1654 audio_update_trackinfo();
1641 1655
@@ -2096,8 +2110,6 @@ void voice_init(void)
2096 { 2110 {
2097 logf("Terminating voice codec"); 2111 logf("Terminating voice codec");
2098 ci_voice.stop_codec = true; 2112 ci_voice.stop_codec = true;
2099 if (current_codec != CODEC_IDX_VOICE)
2100 swap_codec();
2101 sleep(1); 2113 sleep(1);
2102 } 2114 }
2103 2115