summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/buffering.c89
-rw-r--r--apps/playback.c2
2 files changed, 47 insertions, 44 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index e80dc79b54..79144e78db 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -403,10 +403,17 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
403{ 403{
404 struct memory_handle *dest; 404 struct memory_handle *dest;
405 const struct memory_handle *src; 405 const struct memory_handle *src;
406 int32_t *here;
407 int32_t *there;
408 int32_t *end;
409 int32_t *begin;
410 size_t oldpos;
406 size_t newpos; 411 size_t newpos;
407 size_t size_to_move; 412 size_t size_to_move;
408 size_t final_delta = *delta; 413 size_t final_delta = *delta;
414 size_t n;
409 int overlap; 415 int overlap;
416 int overlap_old;
410 417
411 if (h == NULL || (src = *h) == NULL) 418 if (h == NULL || (src = *h) == NULL)
412 return false; 419 return false;
@@ -423,33 +430,34 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
423 mutex_lock(&llist_mutex); 430 mutex_lock(&llist_mutex);
424 mutex_lock(&llist_mod_mutex); 431 mutex_lock(&llist_mod_mutex);
425 432
426 newpos = RINGBUF_ADD((void *)src - (void *)buffer, final_delta); 433 oldpos = (void *)src - (void *)buffer;
434 newpos = RINGBUF_ADD(oldpos, final_delta);
427 overlap = RINGBUF_ADD_CROSS(newpos, size_to_move, buffer_len - 1); 435 overlap = RINGBUF_ADD_CROSS(newpos, size_to_move, buffer_len - 1);
436 overlap_old = RINGBUF_ADD_CROSS(oldpos, size_to_move, buffer_len -1);
428 437
429 if (overlap > 0) { 438 if (overlap > 0) {
430 /* Some part of the struct + data would wrap, maybe ok */ 439 /* Some part of the struct + data would wrap, maybe ok */
431 size_t correction = 0; 440 size_t correction = 0;
432 /* If the overlap lands inside the memory_handle */ 441 /* If the overlap lands inside the memory_handle */
433 if ((unsigned)overlap > data_size) { 442 if (!can_wrap) {
434 /* Correct the position and real delta to prevent the struct from
435 * wrapping, this guarantees an aligned delta, I think */
436 correction = overlap - data_size;
437 } else if (!can_wrap) {
438 /* Otherwise the overlap falls in the data area and must all be 443 /* Otherwise the overlap falls in the data area and must all be
439 * backed out. This may become conditional if ever we move 444 * backed out. This may become conditional if ever we move
440 * data that is allowed to wrap (ie audio) */ 445 * data that is allowed to wrap (ie audio) */
441 correction = overlap; 446 correction = overlap;
442 /* Align correction to four bytes, up */ 447 } else if ((unsigned)overlap > data_size) {
443 correction = (correction+3) & ~3; 448 /* Correct the position and real delta to prevent the struct from
449 * wrapping, this guarantees an aligned delta, I think */
450 correction = overlap - data_size;
444 } 451 }
445 if (correction) { 452 if (correction) {
453 /* Align correction to four bytes up */
454 correction = (correction + 3) & ~3;
446 if (final_delta < correction + sizeof(struct memory_handle)) { 455 if (final_delta < correction + sizeof(struct memory_handle)) {
447 /* Delta cannot end up less than the size of the struct */ 456 /* Delta cannot end up less than the size of the struct */
448 mutex_unlock(&llist_mod_mutex); 457 mutex_unlock(&llist_mod_mutex);
449 mutex_unlock(&llist_mutex); 458 mutex_unlock(&llist_mutex);
450 return false; 459 return false;
451 } 460 }
452
453 newpos -= correction; 461 newpos -= correction;
454 overlap -= correction;/* Used below to know how to split the data */ 462 overlap -= correction;/* Used below to know how to split the data */
455 final_delta -= correction; 463 final_delta -= correction;
@@ -484,38 +492,33 @@ static bool move_handle(struct memory_handle **h, size_t *delta,
484 if (src == cur_handle) 492 if (src == cur_handle)
485 cur_handle = dest; 493 cur_handle = dest;
486 494
487 if (overlap > 0) { 495
488 /* FIXME : this code is broken and can leave the data corrupted when 496 /* Copying routine takes into account that the handles have a
489 * the amount of data to move is close to the whole buffer size. 497 * distance between each other which is a multiple of four. Faster 2 word
490 * 498 * copy may be ok but do this for safety and because wrapped copies should
491 * Example : ('S' is the source data, '-' is empty buffer) 499 * be fairly uncommon */
492 * Size of the buffer is 8 bytes, starts at 0. 500
493 * Size of the data to move is 7 bytes. 501 here = (int32_t *)((RINGBUF_ADD(oldpos, size_to_move - 1) & ~3)+ (intptr_t)buffer);
494 * 502 there =(int32_t *)((RINGBUF_ADD(newpos, size_to_move - 1) & ~3)+ (intptr_t)buffer);
495 * -SSSSSSS 503 end = (int32_t *)(( intptr_t)buffer + buffer_len - 4);
496 * ^-------- start of source data == 1 504 begin =(int32_t *)buffer;
497 * 505
498 * DD-DDDDD ('D' is desired destination data) 506 n = (size_to_move & ~3)/4;
499 * ^------ start of destination data == 3 507
500 * 508 if ( overlap_old > 0 || overlap > 0 ) {
501 * memmove(3, 1, 5); 509 /* Old or moved handle wraps */
502 * memmove(0, 7, 2); 510 while (n--) {
503 * 511 if (here < begin)
504 * First memmove() call will leave the buffer in this state: 512 here = end;
505 * 513 if (there < begin)
506 * -SSDDDDD 514 there = end;
507 * ^^ 515 *there-- = *here--;
508 * \--- data to be moved by the second memmove() call, but 516 }
509 * overwritten by the first call.
510 *
511 * See FS#10605 for more details
512 */
513 size_t first_part = size_to_move - overlap;
514 memmove(dest, src, first_part);
515 memmove(buffer, (const char *)src + first_part, overlap);
516 } else { 517 } else {
517 memmove(dest, src, size_to_move); 518 /* both handles do not wrap */
518 } 519 memmove(dest,src,size_to_move);
520 }
521
519 522
520 /* Update the caller with the new location of h and the distance moved */ 523 /* Update the caller with the new location of h and the distance moved */
521 *h = dest; 524 *h = dest;
@@ -641,10 +644,10 @@ static bool buffer_handle(int handle_id)
641 if (RINGBUF_ADD_CROSS(h->widx, copy_n, buf_ridx) >= 0) 644 if (RINGBUF_ADD_CROSS(h->widx, copy_n, buf_ridx) >= 0)
642 return false; 645 return false;
643 646
644 /* This would read into the next handle, this is broken */ 647 /* This would read into the next handle, this is broken
645 if (h->next && RINGBUF_ADD_CROSS(h->widx, copy_n, 648 if (h->next && RINGBUF_ADD_CROSS(h->widx, copy_n,
646 (unsigned)((void *)h->next - (void *)buffer)) > 0) { 649 (unsigned)((void *)h->next - (void *)buffer)) > 0) {
647 /* Try to recover by truncating this file */ 650 Try to recover by truncating this file
648 copy_n = RINGBUF_ADD_CROSS(h->widx, copy_n, 651 copy_n = RINGBUF_ADD_CROSS(h->widx, copy_n,
649 (unsigned)((void *)h->next - (void *)buffer)); 652 (unsigned)((void *)h->next - (void *)buffer));
650 h->filerem -= copy_n; 653 h->filerem -= copy_n;
@@ -654,7 +657,7 @@ static bool buffer_handle(int handle_id)
654 continue; 657 continue;
655 else 658 else
656 break; 659 break;
657 } 660 } */
658 661
659 /* rc is the actual amount read */ 662 /* rc is the actual amount read */
660 int rc = read(h->fd, &buffer[h->widx], copy_n); 663 int rc = read(h->fd, &buffer[h->widx], copy_n);
diff --git a/apps/playback.c b/apps/playback.c
index f0794faf87..ff20172d83 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -1549,7 +1549,6 @@ static int audio_check_new_track(void)
1549 /* Move to the new track */ 1549 /* Move to the new track */
1550 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK; 1550 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
1551 1551
1552 buf_set_base_handle(CUR_TI->audio_hid);
1553 1552
1554 if (automatic_skip) 1553 if (automatic_skip)
1555 { 1554 {
@@ -1904,6 +1903,7 @@ static void audio_thread(void)
1904 case Q_AUDIO_FINISH_LOAD: 1903 case Q_AUDIO_FINISH_LOAD:
1905 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD"); 1904 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
1906 audio_finish_load_track(); 1905 audio_finish_load_track();
1906 buf_set_base_handle(CUR_TI->audio_hid);
1907 break; 1907 break;
1908 1908
1909 case Q_AUDIO_PLAY: 1909 case Q_AUDIO_PLAY: