Remove the unused "rebuffer" parameters
[Rockbox.git] / apps / buffering.c
bloba39e07151a0d050db7d065429a7ab10867a376d9
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Nicolas Pennequin
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "config.h"
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include "buffering.h"
27 #include "ata.h"
28 #include "system.h"
29 #include "thread.h"
30 #include "file.h"
31 #include "panic.h"
32 #include "memory.h"
33 #include "lcd.h"
34 #include "font.h"
35 #include "button.h"
36 #include "kernel.h"
37 #include "tree.h"
38 #include "debug.h"
39 #include "sprintf.h"
40 #include "settings.h"
41 #include "codecs.h"
42 #include "audio.h"
43 #include "logf.h"
44 #include "mp3_playback.h"
45 #include "usb.h"
46 #include "status.h"
47 #include "screens.h"
48 #include "playlist.h"
49 #include "playback.h"
50 #include "pcmbuf.h"
51 #include "buffer.h"
52 #include "ata_idle_notify.h"
54 #ifdef SIMULATOR
55 #define ata_disk_is_active() 1
56 #endif
58 #if MEM > 1
59 #define GUARD_BUFSIZE (32*1024)
60 #else
61 #define GUARD_BUFSIZE (8*1024)
62 #endif
65 /* macros to enable logf for queues
66 logging on SYS_TIMEOUT can be disabled */
67 #ifdef SIMULATOR
68 /* Define this for logf output of all queuing except SYS_TIMEOUT */
69 #define BUFFERING_LOGQUEUES
70 /* Define this to logf SYS_TIMEOUT messages */
71 /* #define BUFFERING_LOGQUEUES_SYS_TIMEOUT */
72 #endif
74 #ifdef BUFFERING_LOGQUEUES
75 #define LOGFQUEUE logf
76 #else
77 #define LOGFQUEUE(...)
78 #endif
80 #ifdef BUFFERING_LOGQUEUES_SYS_TIMEOUT
81 #define LOGFQUEUE_SYS_TIMEOUT logf
82 #else
83 #define LOGFQUEUE_SYS_TIMEOUT(...)
84 #endif
87 /* amount of data to read in one read() call */
88 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
90 /* Ring buffer helper macros */
91 /* Buffer pointer (p) plus value (v), wrapped if necessary */
92 #define RINGBUF_ADD(p,v) ((p+v)<buffer_len ? p+v : p+v-buffer_len)
93 /* Buffer pointer (p) minus value (v), wrapped if necessary */
94 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+buffer_len-v)
95 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
96 #define RINGBUF_ADD_CROSS(p1,v,p2) \
97 ((p1<p2) ? (int)(p1+v)-(int)p2 : (int)(p1+v-p2)-(int)buffer_len)
98 /* Bytes available in the buffer */
99 #define BUF_USED RINGBUF_SUB(buf_widx, buf_ridx)
101 struct memory_handle {
102 int id; /* A unique ID for the handle */
103 enum data_type type;
104 char path[MAX_PATH];
105 int fd;
106 size_t data; /* Start index of the handle's data buffer */
107 size_t ridx; /* Current read pointer, relative to the main buffer */
108 size_t widx; /* Current write pointer */
109 size_t filesize; /* File total length */
110 size_t filerem; /* Remaining bytes of file NOT in buffer */
111 size_t available; /* Available bytes to read from buffer */
112 size_t offset; /* Offset at which we started reading the file */
113 struct memory_handle *next;
115 /* at all times, we have: filesize == offset + available + filerem */
118 static char *buffer;
119 static char *guard_buffer;
121 static size_t buffer_len;
123 static size_t buf_widx; /* current writing position */
124 static size_t buf_ridx; /* current reading position */
125 /* buf_*idx are values relative to the buffer, not real pointers. */
127 static size_t conf_filechunk = 0;
128 static size_t conf_watermark = 0; /* Level to trigger filebuf fill */
129 #if MEM > 8
130 static size_t high_watermark = 0; /* High watermark for rebuffer */
131 #endif
134 /* current memory handle in the linked list. NULL when the list is empty. */
135 static struct memory_handle *cur_handle;
136 /* first memory handle in the linked list. NULL when the list is empty. */
137 static struct memory_handle *first_handle;
139 static int num_handles; /* number of handles in the list */
141 static int base_handle_id;
143 static struct mutex llist_mutex;
145 /* Handle cache (makes find_handle faster).
146 These need to be global so that move_handle can invalidate them. */
147 static int cached_handle_id = -1;
148 static struct memory_handle *cached_handle = NULL;
150 static buffer_low_callback buffer_low_callback_funcs[MAX_BUF_CALLBACKS];
151 static int buffer_callback_count = 0;
154 /* Messages available to communicate with the buffering thread */
155 enum {
156 Q_BUFFER_HANDLE = 1, /* Request buffering of a handle */
157 Q_RESET_HANDLE, /* (internal) Request resetting of a handle to its
158 offset (the offset has to be set beforehand) */
159 Q_CLOSE_HANDLE,
160 Q_BUFFERING_FILL_BUFFER_IF_ACTIVE_ATA,
161 Q_BASE_HANDLE,
164 /* Buffering thread */
165 void buffering_thread(void);
166 static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
167 static const char buffering_thread_name[] = "buffering";
168 struct thread_entry *buffering_thread_p;
169 struct event_queue buffering_queue;
170 struct queue_sender_list buffering_queue_sender_list;
174 LINKED LIST MANAGEMENT
175 ======================
177 add_handle : Add a handle to the list
178 rm_handle : Remove a handle from the list
179 find_handle : Get a handle pointer from an ID
180 move_handle : Move a handle in the buffer (with or without its data)
182 These functions only handle the linked list structure. They don't touch the
183 contents of the struct memory_handle headers. They also change the buf_*idx
184 pointers when necessary and manage the handle IDs.
186 The first and current (== last) handle are kept track of.
187 A new handle is added at buf_widx and becomes the current one.
188 buf_widx always points to the current writing position for the current handle
189 buf_ridx always points to the location of the first handle.
190 buf_ridx == buf_widx means the buffer is empty.
194 /* Add a new handle to the linked list and return it. It will have become the
195 new current handle. The handle will reserve "data_size" bytes or if that's
196 not possible, decrease "data_size" to allow adding the handle. */
197 static struct memory_handle *add_handle(size_t *data_size)
199 mutex_lock(&llist_mutex);
201 /* this will give each handle a unique id */
202 static int cur_handle_id = 1;
204 /* make sure buf_widx is 32-bit aligned so that the handle struct is,
205 but before that we check we can actually align. */
206 if (RINGBUF_ADD_CROSS(buf_widx, 3, buf_ridx) >= 0) {
207 mutex_unlock(&llist_mutex);
208 return NULL;
210 buf_widx = (RINGBUF_ADD(buf_widx, 3)) & ~3;
212 size_t len = (data_size ? *data_size : 0)
213 + sizeof(struct memory_handle);
215 /* check that we actually can add the handle and its data */
216 int overlap = RINGBUF_ADD_CROSS(buf_widx, len, buf_ridx);
217 if (overlap >= 0) {
218 *data_size -= overlap;
219 len -= overlap;
221 if (len < sizeof(struct memory_handle)) {
222 /* There isn't even enough space to write the struct */
223 mutex_unlock(&llist_mutex);
224 return NULL;
227 struct memory_handle *new_handle =
228 (struct memory_handle *)(&buffer[buf_widx]);
230 /* only advance the buffer write index of the size of the struct */
231 buf_widx = RINGBUF_ADD(buf_widx, sizeof(struct memory_handle));
233 if (!first_handle) {
234 /* the new handle is the first one */
235 first_handle = new_handle;
238 if (cur_handle) {
239 cur_handle->next = new_handle;
242 cur_handle = new_handle;
243 cur_handle->id = cur_handle_id++;
244 cur_handle->next = NULL;
245 num_handles++;
247 mutex_unlock(&llist_mutex);
248 return cur_handle;
251 /* Delete a given memory handle from the linked list
252 and return true for success. Nothing is actually erased from memory. */
253 static bool rm_handle(struct memory_handle *h)
255 mutex_lock(&llist_mutex);
257 if (h == first_handle) {
258 first_handle = h->next;
259 if (h == cur_handle) {
260 /* h was the first and last handle: the buffer is now empty */
261 cur_handle = NULL;
262 buf_ridx = buf_widx;
263 } else {
264 /* update buf_ridx to point to the new first handle */
265 buf_ridx = (void *)first_handle - (void *)buffer;
267 } else {
268 struct memory_handle *m = first_handle;
269 while (m && m->next != h) {
270 m = m->next;
272 if (h && m && m->next == h) {
273 m->next = h->next;
274 if (h == cur_handle) {
275 cur_handle = m;
276 buf_widx = cur_handle->widx;
278 } else {
279 mutex_unlock(&llist_mutex);
280 return false;
284 /* Invalidate the cache to prevent it from keeping the old location of h */
285 if (h == cached_handle)
286 cached_handle = NULL;
288 num_handles--;
290 mutex_unlock(&llist_mutex);
291 return true;
294 /* Return a pointer to the memory handle of given ID.
295 NULL if the handle wasn't found */
296 static struct memory_handle *find_handle(int handle_id)
298 mutex_lock(&llist_mutex);
300 /* simple caching because most of the time the requested handle
301 will either be the same as the last, or the one after the last */
302 if (cached_handle)
304 if (cached_handle_id == handle_id &&
305 cached_handle_id == cached_handle->id) {
306 mutex_unlock(&llist_mutex);
307 return cached_handle;
308 } else if (cached_handle->next &&
309 (cached_handle->next->id == handle_id)) {
310 cached_handle = cached_handle->next;
311 cached_handle_id = handle_id;
312 mutex_unlock(&llist_mutex);
313 return cached_handle;
317 struct memory_handle *m = first_handle;
318 while (m && m->id != handle_id) {
319 m = m->next;
321 cached_handle_id = handle_id;
322 cached_handle = m;
323 struct memory_handle *ret = (m && m->id == handle_id) ? m : NULL;
325 mutex_unlock(&llist_mutex);
326 return ret;
329 /* Move a memory handle and data_size of its data of delta.
330 Return a pointer to the new location of the handle.
331 delta is the value of which to move the struct data.
332 data_size is the amount of data to move along with the struct. */
333 static struct memory_handle *move_handle(struct memory_handle *h,
334 size_t *delta, size_t data_size)
336 mutex_lock(&llist_mutex);
338 if (*delta < 4) {
339 /* aligning backwards would yield a negative result,
340 and moving the handle of such a small amount is a waste
341 of time anyway. */
342 mutex_unlock(&llist_mutex);
343 return NULL;
345 /* make sure delta is 32-bit aligned so that the handle struct is. */
346 *delta = (*delta - 3) & ~3;
348 size_t newpos = RINGBUF_ADD((void *)h - (void *)buffer, *delta);
350 struct memory_handle *dest = (struct memory_handle *)(&buffer[newpos]);
352 /* Invalidate the cache to prevent it from keeping the old location of h */
353 if (h == cached_handle)
354 cached_handle = NULL;
356 /* the cur_handle pointer might need updating */
357 if (h == cur_handle) {
358 cur_handle = dest;
361 if (h == first_handle) {
362 first_handle = dest;
363 buf_ridx = newpos;
364 } else {
365 struct memory_handle *m = first_handle;
366 while (m && m->next != h) {
367 m = m->next;
369 if (h && m && m->next == h) {
370 m->next = dest;
371 } else {
372 mutex_unlock(&llist_mutex);
373 return NULL;
377 memmove(dest, h, sizeof(struct memory_handle) + data_size);
379 mutex_unlock(&llist_mutex);
380 return dest;
385 BUFFER SPACE MANAGEMENT
386 =======================
388 yield_codec : Used by buffer_handle to know if it should interrupt buffering
389 buffer_handle : Buffer data for a handle
390 reset_handle : Reset writing position and data buffer of a handle to its
391 current offset
392 rebuffer_handle : Seek to a nonbuffered part of a handle by rebuffering the data
393 shrink_handle : Free buffer space by moving a handle
394 fill_buffer : Call buffer_handle for all handles that have data to buffer
395 can_add_handle : Indicate whether it's safe to add a handle
396 data_rem : Total amount of data needing to be buffered
397 wasted_space : Total amount of space available for freeing
398 buffered_data : Total amount of data currently in the buffer
400 These functions are used by the buffering thread to manage buffer space.
403 static bool filebuf_is_lowdata(void)
405 return BUF_USED < AUDIO_FILEBUF_CRITICAL;
408 /* Yield to the codec thread for as long as possible if it is in need of data.
409 Return true if the caller should break to let the buffering thread process
410 new queue events */
411 static bool yield_codec(void)
413 yield();
415 if (!queue_empty(&buffering_queue))
416 return true;
418 while (pcmbuf_is_lowdata() && !filebuf_is_lowdata())
420 sleep(2);
422 if (!queue_empty(&buffering_queue))
423 return true;
426 return false;
429 /* Buffer data for the given handle. Return the amount of data buffered
430 or -1 if the handle wasn't found */
431 static ssize_t buffer_handle(int handle_id)
433 DEBUGF("buffer_handle(%d)\n", handle_id);
434 struct memory_handle *h = find_handle(handle_id);
435 if (!h)
436 return -1;
438 if (h->filerem == 0) {
439 /* nothing left to buffer */
440 return 0;
443 if (h->fd < 0) /* file closed, reopen */
445 if (*h->path)
446 h->fd = open(h->path, O_RDONLY);
447 else
448 return -1;
450 if (h->fd < 0)
451 return -1;
453 if (h->offset)
454 lseek(h->fd, h->offset, SEEK_SET);
457 trigger_cpu_boost();
459 ssize_t ret = 0;
460 while (h->filerem > 0)
462 /* max amount to copy */
463 size_t copy_n = MIN( MIN(h->filerem, conf_filechunk),
464 buffer_len - h->widx);
466 /* stop copying if it would overwrite the reading position
467 or the next handle */
468 if (RINGBUF_ADD_CROSS(h->widx, copy_n, buf_ridx) >= 0 || (h->next &&
469 RINGBUF_ADD_CROSS(h->widx, copy_n, (unsigned)
470 ((void *)h->next - (void *)buffer)) > 0))
471 break;
473 /* rc is the actual amount read */
474 int rc = read(h->fd, &buffer[h->widx], copy_n);
476 if (rc < 0)
478 if (h->type == TYPE_CODEC) {
479 DEBUGF("Partial codec\n");
480 break;
483 DEBUGF("File ended %ld bytes early\n", (long)h->filerem);
484 h->filesize -= h->filerem;
485 h->filerem = 0;
486 break;
489 /* Advance buffer */
490 h->widx = RINGBUF_ADD(h->widx, rc);
491 if (h == cur_handle)
492 buf_widx = h->widx;
493 h->available += rc;
494 ret += rc;
495 h->filerem -= rc;
497 /* DEBUGF("buffer_handle(%d): buffered %ld bytes. done: %ld. remaining: %ld.\n",
498 h->id, rc, h->available, h->filerem); */
500 /* Stop buffering if new queue events have arrived */
501 if (yield_codec())
502 break;
505 if (h->filerem == 0) {
506 /* finished buffering the file */
507 close(h->fd);
508 h->fd = -1;
511 DEBUGF("buffer_handle(%d): buffered %ld bytes (%ld of %ld available, "
512 "rem: %ld, off: %ld)\n",
513 handle_id, (long)ret, (long)h->available, (long)h->filesize,
514 (long)h->filerem, (long)h->offset);
516 return ret;
519 void request_buffer_handle(int handle_id)
521 LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE");
522 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
525 void set_base_handle(int handle_id)
527 LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE");
528 queue_post(&buffering_queue, Q_BASE_HANDLE, handle_id);
531 /* Reset writing position and data buffer of a handle to its current offset.
532 Use this after having set the new offset to use.
533 Returns 0 for success or -1 if the handle wasn't found. */
534 static void reset_handle(int handle_id)
536 DEBUGF("reset_handle(%d)\n", handle_id);
538 struct memory_handle *h = find_handle(handle_id);
539 if (!h)
540 return;
542 h->widx = h->data;
543 if (h == cur_handle)
544 buf_widx = h->widx;
545 h->available = 0;
546 h->filerem = h->filesize - h->offset;
548 if (h->fd >= 0) {
549 lseek(h->fd, h->offset, SEEK_SET);
553 /* Seek to a nonbuffered part of a handle by rebuffering the data. */
554 static void rebuffer_handle(int handle_id, size_t newpos)
556 struct memory_handle *h = find_handle(handle_id);
557 if (!h)
558 return;
560 DEBUGF("rebuffer_handle: resetting the handle to offset %ld\n", (long)newpos);
561 h->offset = newpos;
563 LOGFQUEUE("? >| buffering Q_RESET_HANDLE");
564 queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id);
566 LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE");
567 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
569 h->ridx = h->data;
572 static int close_handle(int handle_id)
574 struct memory_handle *h = find_handle(handle_id);
575 if (!h)
576 return -1;
578 if (h->fd >= 0) {
579 close(h->fd);
580 h->fd = -1;
583 rm_handle(h);
584 return 0;
587 /* Free buffer space by moving the handle struct right before the useful
588 part of its data buffer or by moving all the data. */
589 static void shrink_handle(int handle_id)
591 struct memory_handle *h = find_handle(handle_id);
592 if (!h)
593 return;
595 size_t delta;
596 /* The value of delta might change for alignment reasons */
598 if (h->next && (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET ||
599 h->type == TYPE_IMAGE) && h->filerem == 0 )
601 /* metadata handle: we can move all of it */
602 delta = RINGBUF_SUB( (unsigned)((void *)h->next - (void *)buffer),
603 h->data) - h->available;
604 h = move_handle(h, &delta, h->available);
605 if (!h) return;
606 h->data = RINGBUF_ADD(h->data, delta);
607 h->ridx = RINGBUF_ADD(h->ridx, delta);
608 h->widx = RINGBUF_ADD(h->widx, delta);
610 /* when moving a struct mp3entry we need to readjust its pointers. */
611 if (h->type == TYPE_ID3 && h->filesize == sizeof(struct mp3entry)) {
612 adjust_mp3entry((struct mp3entry *)&buffer[h->data],
613 (void *)&buffer[h->data],
614 (void *)&buffer[RINGBUF_SUB(h->data, delta)]);
617 DEBUGF("shrink_handle(%d): metadata, moved by %ld bytes\n",
618 handle_id, (long)delta);
620 else
622 /* only move the handle struct */
623 delta = RINGBUF_SUB(h->ridx, h->data);
624 h = move_handle(h, &delta, 0);
625 if (!h) return;
626 h->data = RINGBUF_ADD(h->data, delta);
627 h->available -= delta;
628 h->offset += delta;
629 DEBUGF("shrink_handle(%d): audio, %ld bytes freed\n",
630 handle_id, (long)delta);
634 /* Fill the buffer by buffering as much data as possible for handles that still
635 have data left to buffer */
636 static void fill_buffer(void)
638 DEBUGF("fill_buffer()\n");
639 struct memory_handle *m = first_handle;
640 while (queue_empty(&buffering_queue) && m) {
641 if (m->filerem > 0) {
642 buffer_handle(m->id);
644 m = m->next;
647 #ifndef SIMULATOR
648 if (queue_empty(&buffering_queue)) {
649 /* only spin the disk down if the filling wasn't interrupted by an
650 event arriving in the queue. */
651 ata_sleep();
653 #endif
656 /* Check whether it's safe to add a new handle and reserve space to let the
657 current one finish buffering its data. Used by bufopen and bufalloc as
658 a preliminary check before even trying to physically add the handle.
659 Returns true if it's ok to add a new handle, false if not.
661 static bool can_add_handle(void)
663 if (cur_handle && cur_handle->filerem > 0) {
664 /* the current handle hasn't finished buffering. We can only add
665 a new one if there is already enough free space to finish
666 the buffering. */
667 if (cur_handle->filerem < (buffer_len - BUF_USED)) {
668 /* Before adding the new handle we reserve some space for the
669 current one to finish buffering its data. */
670 buf_widx = RINGBUF_ADD(buf_widx, cur_handle->filerem);
671 } else {
672 return false;
676 return true;
679 /* Return the total amount of data left to be buffered for all the handles */
680 static size_t data_rem(void)
682 size_t ret = 0;
684 struct memory_handle *m = first_handle;
685 while (m) {
686 ret += m->filerem;
687 m = m->next;
690 return ret;
693 /* Return the amount of data we have but don't need anymore. This data can be
694 safely erased to reclaim buffer space. */
695 static size_t wasted_space(void)
697 size_t ret = 0;
699 struct memory_handle *m = first_handle;
700 while (m) {
701 ret += RINGBUF_SUB(m->ridx, m->data);
702 m = m->next;
705 return ret;
708 static size_t buffered_data(void)
710 size_t ret = 0;
711 struct memory_handle *m = first_handle;
712 while (m) {
713 ret += m->available;
714 m = m->next;
716 return ret;
719 static size_t useful_data(void)
721 size_t ret = 0;
723 struct memory_handle *m = find_handle(base_handle_id);
724 if (!m)
725 m = first_handle;
727 while (m) {
728 ret += m->available - RINGBUF_SUB(m->ridx, m->data);
729 m = m->next;
731 return ret;
734 ssize_t handleoffset(int handle_id)
736 struct memory_handle *h = find_handle(handle_id);
737 if (!h)
738 return -1;
739 return h->offset;
744 BUFFERING API FUNCTIONS
745 =======================
747 bufopen : Request the opening of a new handle for a file
748 bufalloc : Open a new handle for data other than a file.
749 bufclose : Close an open handle
750 bufseek : Set the read pointer in a handle
751 bufadvance : Move the read pointer in a handle
752 bufread : Copy data from a handle into a given buffer
753 bufgetdata : Give a pointer to the handle's data
754 bufused : Return the amount of buffer space used
756 These functions are exported, to allow interaction with the buffer.
757 They take care of the content of the structs, and rely on the linked list
758 management functions for all the actual handle management work.
762 /* Reserve space in the buffer for a file.
763 filename: name of the file to open
764 offset: offset at which to start buffering the file, useful when the first
765 (offset-1) bytes of the file aren't needed.
766 return value: <0 if the file cannot be opened, or one file already
767 queued to be opened, otherwise the handle for the file in the buffer
769 int bufopen(char *file, size_t offset, enum data_type type)
771 if (!can_add_handle())
772 return -2;
774 int fd = open(file, O_RDONLY);
775 if (fd < 0)
776 return -1;
778 size_t size = filesize(fd) - offset;
780 if (type != TYPE_AUDIO &&
781 size + sizeof(struct memory_handle) > buffer_len - buf_widx)
783 /* for types other than audio, the data can't wrap, so we force it */
784 buf_widx = 0;
787 DEBUGF("bufopen: %s (offset: %ld) (%ld bytes needed)...\n",
788 file, (long)offset, (long)size);
790 struct memory_handle *h = add_handle(&size);
791 if (!h)
793 DEBUGF("bufopen: failed to add handle\n");
794 close(fd);
795 return -2;
798 strncpy(h->path, file, MAX_PATH);
799 h->fd = -1;
800 h->filesize = filesize(fd);
801 h->filerem = h->filesize - offset;
802 h->offset = offset;
803 h->ridx = buf_widx;
804 h->widx = buf_widx;
805 h->data = buf_widx;
806 h->available = 0;
807 h->type = type;
809 close(fd);
811 DEBUGF("bufopen: allocated %ld bytes. ID: %d\n", (long)size, h->id);
813 if (type == TYPE_CODEC || type == TYPE_CUESHEET || type == TYPE_IMAGE) {
814 /* Immediately buffer those */
815 LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE");
816 queue_send(&buffering_queue, Q_BUFFER_HANDLE, h->id);
819 DEBUGF("bufopen: opened handle %d\n", h->id);
820 return h->id;
823 /* Open a new handle from data that needs to be copied from memory.
824 src is the source buffer from which to copy data. It can be NULL to simply
825 reserve buffer space.
826 size is the requested size. The call will only be successful if the
827 requested amount of data can entirely fit in the buffer without wrapping.
828 Return value is the handle id for success or <0 for failure.
830 int bufalloc(void *src, size_t size, enum data_type type)
832 if (!can_add_handle())
833 return -2;
835 if (size + sizeof(struct memory_handle) > buffer_len - buf_widx) {
836 /* The data would need to wrap. */
837 DEBUGF("bufalloc: data wrap\n");
838 return -2;
841 size_t allocsize = size;
842 struct memory_handle *h = add_handle(&allocsize);
844 if (!h || allocsize != size)
845 return -2;
847 if (src) {
848 if (type == TYPE_ID3 && size == sizeof(struct mp3entry)) {
849 DEBUGF("bufalloc: allocating metadata\n");
850 /* specially take care of struct mp3entry */
851 copy_mp3entry((struct mp3entry *)&buffer[buf_widx],
852 (struct mp3entry *)src);
853 } else {
854 memcpy(&buffer[buf_widx], src, size);
858 h->fd = -1;
859 *h->path = 0;
860 h->filesize = size;
861 h->filerem = 0;
862 h->offset = 0;
863 h->ridx = buf_widx;
864 h->widx = buf_widx;
865 h->data = buf_widx;
866 h->available = size;
867 h->type = type;
869 buf_widx = RINGBUF_ADD(buf_widx, size);
871 DEBUGF("bufalloc: opened handle %d\n", h->id);
872 return h->id;
875 /* Close the handle. Return 0 for success and < 0 for failure */
876 int bufclose(int handle_id)
878 DEBUGF("bufclose(%d)\n", handle_id);
880 LOGFQUEUE("buffering >| Q_CLOSE_HANDLE");
881 return queue_send(&buffering_queue, Q_CLOSE_HANDLE, handle_id);
884 /* Set reading index in handle (relatively to the start of the file).
885 Access before the available data will trigger a rebuffer.
886 Return 0 for success and < 0 for failure:
887 -1 if the handle wasn't found
888 -2 if the new requested position was beyond the end of the file
890 int bufseek(int handle_id, size_t newpos)
892 struct memory_handle *h = find_handle(handle_id);
893 if (!h)
894 return -1;
896 if (newpos > h->filesize) {
897 /* access beyond the end of the file */
898 return -3;
900 else if (newpos < h->offset || h->offset + h->available < newpos) {
901 /* access before or after buffered data. A rebuffer is needed. */
902 rebuffer_handle(handle_id, newpos);
904 else {
905 h->ridx = RINGBUF_ADD(h->data, newpos - h->offset);
907 return 0;
910 /* Advance the reading index in a handle (relatively to its current position).
911 Return 0 for success and < 0 for failure */
912 int bufadvance(int handle_id, off_t offset)
914 struct memory_handle *h = find_handle(handle_id);
915 if (!h)
916 return -1;
918 size_t newpos = h->offset + RINGBUF_SUB(h->ridx, h->data) + offset;
920 return bufseek(handle_id, newpos);
923 /* Copy data from the given handle to the dest buffer.
924 Return the number of bytes copied or < 0 for failure. */
925 ssize_t bufread(int handle_id, size_t size, void *dest)
927 struct memory_handle *h = find_handle(handle_id);
928 size_t buffered_data;
929 if (!h)
930 return -1;
932 if (size == 0 && h->filerem > 0 &&
933 h->available - RINGBUF_SUB(h->ridx, h->data) == 0)
934 /* Data isn't ready */
935 return -2;
937 if (h->available - RINGBUF_SUB(h->ridx, h->data) < size && h->filerem > 0)
938 /* Data isn't ready */
939 return -2;
941 if (h->available - RINGBUF_SUB(h->ridx, h->data) == 0 && h->filerem == 0)
942 /* File is finished reading */
943 return 0;
945 buffered_data = MIN(size, h->available - RINGBUF_SUB(h->ridx, h->data));
947 if (h->ridx + buffered_data > buffer_len)
949 /* the data wraps around the end of the buffer */
950 size_t read = buffer_len - h->ridx;
951 memcpy(dest, &buffer[h->ridx], read);
952 memcpy(dest+read, buffer, buffered_data - read);
954 else memcpy(dest, &buffer[h->ridx], buffered_data);
956 return buffered_data;
959 /* Update the "data" pointer to make the handle's data available to the caller.
960 Return the length of the available linear data or < 0 for failure.
961 size is the amount of linear data requested. it can be 0 to get as
962 much as possible.
963 The guard buffer may be used to provide the requested size */
964 ssize_t bufgetdata(int handle_id, size_t size, void **data)
966 struct memory_handle *h = find_handle(handle_id);
967 if (!h)
968 return -1;
970 if (size == 0 && h->filerem > 0 &&
971 h->available - RINGBUF_SUB(h->ridx, h->data) == 0)
972 /* Data isn't ready */
973 return -2;
975 if (h->available - RINGBUF_SUB(h->ridx, h->data) < size && h->filerem > 0)
976 /* Data isn't ready */
977 return -2;
979 if (h->available - RINGBUF_SUB(h->ridx, h->data) == 0 && h->filerem == 0)
980 /* File is finished reading */
981 return 0;
983 ssize_t ret;
985 if (h->ridx + size > buffer_len &&
986 h->available - RINGBUF_SUB(h->ridx, h->data) >= size)
988 /* the data wraps around the end of the buffer :
989 use the guard buffer to provide the requested amount of data. */
990 size_t copy_n = MIN(h->ridx + size - buffer_len, GUARD_BUFSIZE);
991 memcpy(guard_buffer, (unsigned char *)buffer, copy_n);
992 ret = buffer_len - h->ridx + copy_n;
993 DEBUGF("used the guard buffer to complete\n");
995 else
997 ret = MIN(h->available - RINGBUF_SUB(h->ridx, h->data),
998 buffer_len - h->ridx);
1001 *data = &buffer[h->ridx];
1003 /* DEBUGF("bufgetdata(%d): h->ridx=%ld, ret=%ld\n", handle_id,
1004 (long)h->ridx, ret); */
1005 return ret;
1008 /* Return the amount of buffer space used */
1009 size_t bufused(void)
1011 return BUF_USED;
1014 /* Initialise the buffering subsystem */
1015 bool buffering_init(char *filebuf, size_t filebuflen)
1017 if (!filebuf || !filebuflen)
1018 return false;
1020 buffer = filebuf;
1021 buffer_len = filebuflen;
1022 guard_buffer = buffer + buffer_len;
1024 buf_widx = 0;
1025 buf_ridx = 0;
1027 first_handle = NULL;
1028 num_handles = 0;
1030 buffer_callback_count = 0;
1031 memset(buffer_low_callback_funcs, 0, sizeof(buffer_low_callback_funcs));
1033 mutex_init(&llist_mutex);
1035 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
1036 conf_watermark = AUDIO_DEFAULT_WATERMARK;
1038 /* Set the high watermark as 75% full...or 25% empty :) */
1039 #if MEM > 8
1040 high_watermark = 3*filebuflen / 4;
1041 #endif
1043 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
1044 sizeof(buffering_stack), 0,
1045 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
1046 IF_COP(, CPU));
1048 queue_init(&buffering_queue, true);
1049 queue_enable_queue_send(&buffering_queue, &buffering_queue_sender_list);
1051 return true;
1054 #if MEM > 8
1055 /* we dont want this rebuffering on targets with little ram
1056 because the disk may never spin down */
1057 static bool ata_fillbuffer_callback(void)
1059 queue_post(&buffering_queue, Q_BUFFERING_FILL_BUFFER_IF_ACTIVE_ATA, 0);
1060 return true;
1062 #endif
1064 bool register_buffer_low_callback(buffer_low_callback func)
1066 int i;
1067 if (buffer_callback_count >= MAX_BUF_CALLBACKS)
1068 return false;
1069 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1071 if (buffer_low_callback_funcs[i] == NULL)
1073 buffer_low_callback_funcs[i] = func;
1074 buffer_callback_count++;
1075 return true;
1077 else if (buffer_low_callback_funcs[i] == func)
1078 return true;
1080 return false;
1083 void unregister_buffer_low_callback(buffer_low_callback func)
1085 int i;
1086 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1088 if (buffer_low_callback_funcs[i] == func)
1090 buffer_low_callback_funcs[i] = NULL;
1091 buffer_callback_count--;
1094 return;
1097 static void call_buffer_low_callbacks(void)
1099 int i;
1100 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1102 if (buffer_low_callback_funcs[i])
1104 buffer_low_callback_funcs[i]();
1105 buffer_low_callback_funcs[i] = NULL;
1106 buffer_callback_count--;
1111 void buffering_thread(void)
1113 struct queue_event ev;
1115 while (true)
1117 queue_wait_w_tmo(&buffering_queue, &ev, HZ/2);
1119 #if MEM > 8
1120 if ((ev.id == SYS_TIMEOUT) && (buffered_data() < high_watermark))
1121 register_ata_idle_func(ata_fillbuffer_callback);
1122 #endif
1124 switch (ev.id)
1126 case Q_BUFFER_HANDLE:
1127 LOGFQUEUE("buffering < Q_BUFFER_HANDLE");
1128 queue_reply(&buffering_queue, 1);
1129 buffer_handle((int)ev.data);
1130 break;
1132 case Q_RESET_HANDLE:
1133 LOGFQUEUE("buffering < Q_RESET_HANDLE");
1134 queue_reply(&buffering_queue, 1);
1135 reset_handle((int)ev.data);
1136 break;
1138 case Q_CLOSE_HANDLE:
1139 LOGFQUEUE("buffering < Q_CLOSE_HANDLE");
1140 queue_reply(&buffering_queue, close_handle((int)ev.data));
1141 break;
1143 case Q_BASE_HANDLE:
1144 LOGFQUEUE("buffering < Q_BASE_HANDLE");
1145 base_handle_id = (int)ev.data;
1146 break;
1148 #if MEM > 8
1149 case Q_BUFFERING_FILL_BUFFER_IF_ACTIVE_ATA:
1150 /* only fill if the disk is still spining */
1151 #ifndef SIMULATOR
1152 if (!ata_disk_is_active())
1153 break;
1154 #endif
1155 if (num_handles > 0 && data_rem() > 0)
1156 fill_buffer();
1157 break;
1158 #endif /* MEM > 8 */
1160 #ifndef SIMULATOR
1161 case SYS_USB_CONNECTED:
1162 LOGFQUEUE("buffering < SYS_USB_CONNECTED");
1163 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1164 usb_wait_for_disconnect(&buffering_queue);
1165 break;
1166 #endif
1168 case SYS_TIMEOUT:
1169 LOGFQUEUE_SYS_TIMEOUT("buffering < SYS_TIMEOUT");
1170 break;
1173 if (first_handle && useful_data() < conf_watermark)
1175 DEBUGF("buffer is low on useful data, calling the callbacks\n");
1176 call_buffer_low_callbacks();
1179 if (ev.id == SYS_TIMEOUT && queue_empty(&buffering_queue))
1181 if (data_rem() > 0 && wasted_space() > buffered_data()/2)
1183 DEBUGF("there is %ld bytes of wasted space\n",
1184 (long)wasted_space());
1186 /* free buffer from outdated audio data */
1187 struct memory_handle *m = first_handle;
1188 while (m) {
1189 if (m->type == TYPE_AUDIO)
1190 shrink_handle(m->id);
1191 m = m->next;
1194 /* free buffer by moving metadata */
1195 m = first_handle;
1196 while (m) {
1197 if (m->type != TYPE_AUDIO)
1198 shrink_handle(m->id);
1199 m = m->next;
1204 if (data_rem() > 0 && buffered_data() < conf_watermark)
1206 DEBUGF("%ld bytes left to buffer and the buffer is low\n",
1207 (long)data_rem());
1209 fill_buffer();
1215 /* Get a buffer offset from a pointer */
1216 ssize_t get_offset(int handle_id, void *ptr)
1218 struct memory_handle *h = find_handle(handle_id);
1219 if (!h)
1220 return -1;
1222 return (size_t)ptr - (size_t)&buffer[h->ridx];
1225 void buffering_get_debugdata(struct buffering_debug *dbgdata)
1227 dbgdata->num_handles = num_handles;
1228 dbgdata->data_rem = data_rem();
1229 dbgdata->wasted_space = wasted_space();
1230 dbgdata->buffered_data = buffered_data();
1231 dbgdata->useful_data = useful_data();