Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Revert "buffering: remove bufgettail/bufcuttail"

This reverts commit 9e93796407ecb8a347f9799c0a03e80939004bd7.

Fixes FS#13626, which is caused by non-audio ID3v1/APE tags at
the end of the audio data stream.

Change-Id: Ic69af14a5d1264b7896a54b5f2ad314022dd98ac

+107 -2
+56
apps/buffering.c
··· 1440 1440 return size; 1441 1441 } 1442 1442 1443 + ssize_t bufgettail(int handle_id, size_t size, void **data) 1444 + { 1445 + if (thread_self() != buffering_thread_id) 1446 + return ERR_WRONG_THREAD; /* only from buffering thread */ 1447 + 1448 + /* We don't support tail requests of > guardbuf_size, for simplicity */ 1449 + if (size > GUARD_BUFSIZE) 1450 + return ERR_INVALID_VALUE; 1451 + 1452 + const struct memory_handle *h = find_handle(handle_id); 1453 + if (!h) 1454 + return ERR_HANDLE_NOT_FOUND; 1455 + 1456 + if (h->end >= h->filesize) { 1457 + size_t tidx = ringbuf_sub_empty(h->widx, size); 1458 + 1459 + if (tidx + size > buffer_len) { 1460 + size_t copy_n = tidx + size - buffer_len; 1461 + memcpy(guard_buffer, ringbuf_ptr(0), copy_n); 1462 + } 1463 + 1464 + *data = ringbuf_ptr(tidx); 1465 + } 1466 + else { 1467 + size = ERR_HANDLE_NOT_DONE; 1468 + } 1469 + 1470 + return size; 1471 + } 1472 + 1473 + ssize_t bufcuttail(int handle_id, size_t size) 1474 + { 1475 + if (thread_self() != buffering_thread_id) 1476 + return ERR_WRONG_THREAD; /* only from buffering thread */ 1477 + 1478 + struct memory_handle *h = find_handle(handle_id); 1479 + if (!h) 1480 + return ERR_HANDLE_NOT_FOUND; 1481 + 1482 + if (h->end >= h->filesize) { 1483 + /* Cannot trim to before read position */ 1484 + size_t available = h->end - MAX(h->start, h->pos); 1485 + if (available < size) 1486 + size = available; 1487 + 1488 + h->widx = ringbuf_sub_empty(h->widx, size); 1489 + h->filesize -= size; 1490 + h->end -= size; 1491 + } else { 1492 + size = ERR_HANDLE_NOT_DONE; 1493 + } 1494 + 1495 + return size; 1496 + } 1497 + 1498 + 1443 1499 /* 1444 1500 SECONDARY EXPORTED FUNCTIONS 1445 1501 ============================
+6 -1
apps/buffering.h
··· 46 46 #define ERR_FILE_ERROR -4 47 47 #define ERR_HANDLE_NOT_DONE -5 48 48 #define ERR_UNSUPPORTED_TYPE -6 49 - #define ERR_BITMAP_TOO_LARGE -7 49 + #define ERR_WRONG_THREAD -7 50 + #define ERR_BITMAP_TOO_LARGE -8 50 51 51 52 /* Initialise the buffering subsystem */ 52 53 void buffering_init(void) INIT_ATTR; ··· 67 68 * bufftell : Return the handle's file read position 68 69 * bufread : Copy data from a handle to a buffer 69 70 * bufgetdata: Obtain a pointer for linear access to a "size" amount of data 71 + * bufgettail: Out-of-band get the last size bytes of a handle. 72 + * bufcuttail: Out-of-band remove the trailing 'size' bytes of a handle. 70 73 * 71 74 * NOTE: bufread and bufgetdata will block the caller until the requested 72 75 * amount of data is ready (unless EOF is reached). ··· 82 85 off_t bufftell(int handle_id); 83 86 ssize_t bufread(int handle_id, size_t size, void *dest); 84 87 ssize_t bufgetdata(int handle_id, size_t size, void **data); 88 + ssize_t bufgettail(int handle_id, size_t size, void **data); 89 + ssize_t bufcuttail(int handle_id, size_t size); 85 90 86 91 /*************************************************************************** 87 92 * SECONDARY FUNCTIONS
+6 -1
apps/playback.c
··· 1255 1255 playback_log_handle = core_alloc(PLAYBACK_LOG_BUFSZ); 1256 1256 if (playback_log_handle > 0) 1257 1257 { 1258 - DEBUGF("%s Allocated %d bytes\n", __func__, PLAYBACK_LOG_BUFSZ); 1258 + DEBUGF("%s Allocated %d bytes\n", __func__, PLAYBACK_LOG_BUFSZ); 1259 1259 char *buf = core_get_data(playback_log_handle); 1260 1260 buf[0] = '\0'; 1261 1261 } ··· 3748 3748 break; 3749 3749 3750 3750 case TYPE_PACKET_AUDIO: 3751 + /* Strip any useless trailing tags that are left. 3752 + Note this is needed to prevent playback noise at the 3753 + end of MP3 files with ID3v1 or APEv2 tags! */ 3754 + strip_tags(hid); 3755 + /* Fall-through */ 3751 3756 case TYPE_ATOMIC_AUDIO: 3752 3757 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid); 3753 3758 audio_queue_post(Q_AUDIO_HANDLE_FINISHED, hid);
+38
lib/rbcodec/metadata/metadata.c
··· 499 499 return get_metadata_ex(id3, fd, trackname, 0); 500 500 } 501 501 502 + #ifndef __PCTOOL__ 503 + void strip_tags(int handle_id) 504 + { 505 + static const unsigned char tag[] = "TAG"; 506 + static const unsigned char apetag[] = "APETAGEX"; 507 + size_t len, version; 508 + void *tail; 509 + 510 + if (bufgettail(handle_id, 128, &tail) != 128) 511 + return; 512 + 513 + if (memcmp(tail, tag, 3) == 0) 514 + { 515 + /* Skip id3v1 tag */ 516 + logf("Cutting off ID3v1 tag"); 517 + bufcuttail(handle_id, 128); 518 + } 519 + 520 + /* Get a new tail, as the old one may have been cut */ 521 + if (bufgettail(handle_id, 32, &tail) != 32) 522 + return; 523 + 524 + /* Check for APE tag (look for the APE tag footer) */ 525 + if (memcmp(tail, apetag, 8) != 0) 526 + return; 527 + 528 + /* Read the version and length from the footer */ 529 + version = get_long_le(&((unsigned char *)tail)[8]); 530 + len = get_long_le(&((unsigned char *)tail)[12]); 531 + if (version == 2000) 532 + len += 32; /* APEv2 has a 32 byte header */ 533 + 534 + /* Skip APE tag */ 535 + logf("Cutting off APE tag (%ldB)", len); 536 + bufcuttail(handle_id, len); 537 + } 538 + #endif /* ! __PCTOOL__ */ 539 + 502 540 #define MOVE_ENTRY(x) if (x) x += offset; 503 541 504 542 void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig)
+1
lib/rbcodec/metadata/metadata.h
··· 338 338 void fill_metadata_from_path(struct mp3entry *id3, const char *trackname); 339 339 int get_audio_base_codec_type(int type); 340 340 const char * get_codec_string(int type); 341 + void strip_tags(int handle_id); 341 342 bool rbcodec_format_is_atomic(int afmt); 342 343 bool format_buffers_with_offset(int afmt); 343 344