Improve bufgetdata and bufread
[Rockbox.git] / apps / buffering.c
blob1d258de3eb232706fc98254649891fc68ed608bc
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"
53 #ifdef SIMULATOR
54 #define ata_disk_is_active() 1
55 #endif
57 #if MEM > 1
58 #define GUARD_BUFSIZE (32*1024)
59 #else
60 #define GUARD_BUFSIZE (8*1024)
61 #endif
64 /* macros to enable logf for queues
65 logging on SYS_TIMEOUT can be disabled */
66 #ifdef SIMULATOR
67 /* Define this for logf output of all queuing except SYS_TIMEOUT */
68 #define BUFFERING_LOGQUEUES
69 /* Define this to logf SYS_TIMEOUT messages */
70 /* #define BUFFERING_LOGQUEUES_SYS_TIMEOUT */
71 #endif
73 #ifdef BUFFERING_LOGQUEUES
74 #define LOGFQUEUE logf
75 #else
76 #define LOGFQUEUE(...)
77 #endif
79 #ifdef BUFFERING_LOGQUEUES_SYS_TIMEOUT
80 #define LOGFQUEUE_SYS_TIMEOUT logf
81 #else
82 #define LOGFQUEUE_SYS_TIMEOUT(...)
83 #endif
86 /* amount of data to read in one read() call */
87 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
89 /* Ring buffer helper macros */
90 /* Buffer pointer (p) plus value (v), wrapped if necessary */
91 #define RINGBUF_ADD(p,v) ((p+v)<buffer_len ? p+v : p+v-buffer_len)
92 /* Buffer pointer (p) minus value (v), wrapped if necessary */
93 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+buffer_len-v)
94 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
95 #define RINGBUF_ADD_CROSS(p1,v,p2) \
96 ((p1<p2) ? (int)(p1+v)-(int)p2 : (int)(p1+v-p2)-(int)buffer_len)
97 /* Bytes available in the buffer */
98 #define BUF_USED RINGBUF_SUB(buf_widx, buf_ridx)
100 struct memory_handle {
101 int id; /* A unique ID for the handle */
102 enum data_type type;
103 char path[MAX_PATH];
104 int fd;
105 size_t data; /* Start index of the handle's data buffer */
106 volatile size_t ridx; /* Current read pointer, relative to the main buffer */
107 size_t widx; /* Current write pointer */
108 size_t filesize; /* File total length */
109 size_t filerem; /* Remaining bytes of file NOT in buffer */
110 volatile size_t available; /* Available bytes to read from buffer */
111 size_t offset; /* Offset at which we started reading the file */
112 struct memory_handle *next;
114 /* at all times, we have: filesize == offset + available + filerem */
117 static char *buffer;
118 static char *guard_buffer;
120 static size_t buffer_len;
122 static volatile size_t buf_widx; /* current writing position */
123 static volatile size_t buf_ridx; /* current reading position */
124 /* buf_*idx are values relative to the buffer, not real pointers. */
126 static size_t conf_filechunk = 0;
127 static size_t conf_watermark = 0; /* Level to trigger filebuf fill */
128 #if MEM > 8
129 static size_t high_watermark = 0; /* High watermark for rebuffer */
130 #endif
133 /* current memory handle in the linked list. NULL when the list is empty. */
134 static struct memory_handle *cur_handle;
135 /* first memory handle in the linked list. NULL when the list is empty. */
136 static struct memory_handle *first_handle;
138 static int num_handles; /* number of handles in the list */
140 static int base_handle_id;
142 static struct mutex llist_mutex;
144 /* Handle cache (makes find_handle faster).
145 These need to be global so that move_handle can invalidate them. */
146 static int cached_handle_id = -1;
147 static struct memory_handle *cached_handle = NULL;
149 static buffer_low_callback buffer_low_callback_funcs[MAX_BUF_CALLBACKS];
150 static int buffer_callback_count = 0;
153 /* Messages available to communicate with the buffering thread */
154 enum {
155 Q_BUFFER_HANDLE = 1, /* Request buffering of a handle */
156 Q_RESET_HANDLE, /* (internal) Request resetting of a handle to its
157 offset (the offset has to be set beforehand) */
158 Q_CLOSE_HANDLE, /* Request closing a handle */
159 Q_BASE_HANDLE, /* Set the reference handle for buf_useful_data */
162 /* Buffering thread */
163 void buffering_thread(void);
164 static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
165 static const char buffering_thread_name[] = "buffering";
166 static struct thread_entry *buffering_thread_p;
167 static struct event_queue buffering_queue;
168 static struct queue_sender_list buffering_queue_sender_list;
172 LINKED LIST MANAGEMENT
173 ======================
175 add_handle : Add a handle to the list
176 rm_handle : Remove a handle from the list
177 find_handle : Get a handle pointer from an ID
178 move_handle : Move a handle in the buffer (with or without its data)
180 These functions only handle the linked list structure. They don't touch the
181 contents of the struct memory_handle headers. They also change the buf_*idx
182 pointers when necessary and manage the handle IDs.
184 The first and current (== last) handle are kept track of.
185 A new handle is added at buf_widx and becomes the current one.
186 buf_widx always points to the current writing position for the current handle
187 buf_ridx always points to the location of the first handle.
188 buf_ridx == buf_widx means the buffer is empty.
192 /* Add a new handle to the linked list and return it. It will have become the
193 new current handle. The handle will reserve "data_size" bytes or if that's
194 not possible, decrease "data_size" to allow adding the handle. */
195 static struct memory_handle *add_handle(size_t *data_size)
197 mutex_lock(&llist_mutex);
199 /* this will give each handle a unique id */
200 static int cur_handle_id = 1;
202 /* make sure buf_widx is 32-bit aligned so that the handle struct is,
203 but before that we check we can actually align. */
204 if (RINGBUF_ADD_CROSS(buf_widx, 3, buf_ridx) >= 0) {
205 mutex_unlock(&llist_mutex);
206 return NULL;
208 buf_widx = (RINGBUF_ADD(buf_widx, 3)) & ~3;
210 size_t len = (data_size ? *data_size : 0)
211 + sizeof(struct memory_handle);
213 /* check that we actually can add the handle and its data */
214 int overlap = RINGBUF_ADD_CROSS(buf_widx, len, buf_ridx);
215 if (overlap >= 0) {
216 *data_size -= overlap;
217 len -= overlap;
219 if (len < sizeof(struct memory_handle)) {
220 /* There isn't even enough space to write the struct */
221 mutex_unlock(&llist_mutex);
222 return NULL;
225 struct memory_handle *new_handle =
226 (struct memory_handle *)(&buffer[buf_widx]);
228 /* only advance the buffer write index of the size of the struct */
229 buf_widx = RINGBUF_ADD(buf_widx, sizeof(struct memory_handle));
231 if (!first_handle) {
232 /* the new handle is the first one */
233 first_handle = new_handle;
236 if (cur_handle) {
237 cur_handle->next = new_handle;
240 cur_handle = new_handle;
241 cur_handle->id = cur_handle_id++;
242 cur_handle->next = NULL;
243 num_handles++;
245 mutex_unlock(&llist_mutex);
246 return cur_handle;
249 /* Delete a given memory handle from the linked list
250 and return true for success. Nothing is actually erased from memory. */
251 static bool rm_handle(struct memory_handle *h)
253 mutex_lock(&llist_mutex);
255 if (h == first_handle) {
256 first_handle = h->next;
257 if (h == cur_handle) {
258 /* h was the first and last handle: the buffer is now empty */
259 cur_handle = NULL;
260 buf_ridx = buf_widx;
261 } else {
262 /* update buf_ridx to point to the new first handle */
263 buf_ridx = (void *)first_handle - (void *)buffer;
265 } else {
266 struct memory_handle *m = first_handle;
267 while (m && m->next != h) {
268 m = m->next;
270 if (h && m && m->next == h) {
271 m->next = h->next;
272 if (h == cur_handle) {
273 cur_handle = m;
274 buf_widx = cur_handle->widx;
276 } else {
277 mutex_unlock(&llist_mutex);
278 return false;
282 /* Invalidate the cache to prevent it from keeping the old location of h */
283 if (h == cached_handle)
284 cached_handle = NULL;
286 num_handles--;
288 mutex_unlock(&llist_mutex);
289 return true;
292 /* Return a pointer to the memory handle of given ID.
293 NULL if the handle wasn't found */
294 static struct memory_handle *find_handle(int handle_id)
296 mutex_lock(&llist_mutex);
298 /* simple caching because most of the time the requested handle
299 will either be the same as the last, or the one after the last */
300 if (cached_handle)
302 if (cached_handle_id == handle_id &&
303 cached_handle_id == cached_handle->id) {
304 mutex_unlock(&llist_mutex);
305 return cached_handle;
306 } else if (cached_handle->next &&
307 (cached_handle->next->id == handle_id)) {
308 cached_handle = cached_handle->next;
309 cached_handle_id = handle_id;
310 mutex_unlock(&llist_mutex);
311 return cached_handle;
315 struct memory_handle *m = first_handle;
316 while (m && m->id != handle_id) {
317 m = m->next;
319 cached_handle_id = handle_id;
320 cached_handle = m;
321 struct memory_handle *ret = (m && m->id == handle_id) ? m : NULL;
323 mutex_unlock(&llist_mutex);
324 return ret;
327 /* Move a memory handle and data_size of its data of delta.
328 Return a pointer to the new location of the handle.
329 delta is the value of which to move the struct data.
330 data_size is the amount of data to move along with the struct. */
331 static struct memory_handle *move_handle(struct memory_handle *h,
332 size_t *delta, size_t data_size)
334 mutex_lock(&llist_mutex);
336 if (*delta < 4) {
337 /* aligning backwards would yield a negative result,
338 and moving the handle of such a small amount is a waste
339 of time anyway. */
340 mutex_unlock(&llist_mutex);
341 return NULL;
343 /* make sure delta is 32-bit aligned so that the handle struct is. */
344 *delta = (*delta - 3) & ~3;
346 size_t newpos = RINGBUF_ADD((void *)h - (void *)buffer, *delta);
348 struct memory_handle *dest = (struct memory_handle *)(&buffer[newpos]);
350 /* Invalidate the cache to prevent it from keeping the old location of h */
351 if (h == cached_handle)
352 cached_handle = NULL;
354 /* the cur_handle pointer might need updating */
355 if (h == cur_handle) {
356 cur_handle = dest;
359 if (h == first_handle) {
360 first_handle = dest;
361 buf_ridx = newpos;
362 } else {
363 struct memory_handle *m = first_handle;
364 while (m && m->next != h) {
365 m = m->next;
367 if (h && m && m->next == h) {
368 m->next = dest;
369 } else {
370 mutex_unlock(&llist_mutex);
371 return NULL;
375 memmove(dest, h, sizeof(struct memory_handle) + data_size);
377 mutex_unlock(&llist_mutex);
378 return dest;
383 BUFFER SPACE MANAGEMENT
384 =======================
386 yield_codec : Used by buffer_handle to know if it should interrupt buffering
387 buffer_handle : Buffer data for a handle
388 reset_handle : Reset writing position and data buffer of a handle to its
389 current offset
390 rebuffer_handle : Seek to a nonbuffered part of a handle by rebuffering the data
391 shrink_handle : Free buffer space by moving a handle
392 fill_buffer : Call buffer_handle for all handles that have data to buffer
393 can_add_handle : Indicate whether it's safe to add a handle
394 data_rem : Total amount of data needing to be buffered
395 wasted_space : Total amount of space available for freeing
396 buffered_data : Total amount of data currently in the buffer
398 These functions are used by the buffering thread to manage buffer space.
401 static bool filebuf_is_lowdata(void)
403 return BUF_USED < AUDIO_FILEBUF_CRITICAL;
406 /* Yield to the codec thread for as long as possible if it is in need of data.
407 Return true if the caller should break to let the buffering thread process
408 new queue events */
409 static bool yield_codec(void)
411 yield();
413 if (!queue_empty(&buffering_queue))
414 return true;
416 while (pcmbuf_is_lowdata() && !filebuf_is_lowdata())
418 sleep(2);
420 if (!queue_empty(&buffering_queue))
421 return true;
424 return false;
427 /* Buffer data for the given handle. Return the amount of data buffered
428 or -1 if the handle wasn't found */
429 static ssize_t buffer_handle(int handle_id)
431 DEBUGF("buffer_handle(%d)\n", handle_id);
432 struct memory_handle *h = find_handle(handle_id);
433 if (!h)
434 return -1;
436 if (h->filerem == 0) {
437 /* nothing left to buffer */
438 return 0;
441 if (h->fd < 0) /* file closed, reopen */
443 if (*h->path)
444 h->fd = open(h->path, O_RDONLY);
445 else
446 return -1;
448 if (h->fd < 0)
449 return -1;
451 if (h->offset)
452 lseek(h->fd, h->offset, SEEK_SET);
455 trigger_cpu_boost();
457 ssize_t ret = 0;
458 while (h->filerem > 0)
460 /* max amount to copy */
461 size_t copy_n = MIN( MIN(h->filerem, conf_filechunk),
462 buffer_len - h->widx);
464 /* stop copying if it would overwrite the reading position
465 or the next handle */
466 if (RINGBUF_ADD_CROSS(h->widx, copy_n, buf_ridx) >= 0 || (h->next &&
467 RINGBUF_ADD_CROSS(h->widx, copy_n, (unsigned)
468 ((void *)h->next - (void *)buffer)) > 0))
469 break;
471 /* rc is the actual amount read */
472 int rc = read(h->fd, &buffer[h->widx], copy_n);
474 if (rc < 0)
476 if (h->type == TYPE_CODEC) {
477 DEBUGF("Partial codec\n");
478 break;
481 DEBUGF("File ended %ld bytes early\n", (long)h->filerem);
482 h->filesize -= h->filerem;
483 h->filerem = 0;
484 break;
487 /* Advance buffer */
488 h->widx = RINGBUF_ADD(h->widx, rc);
489 if (h == cur_handle)
490 buf_widx = h->widx;
491 h->available += rc;
492 ret += rc;
493 h->filerem -= rc;
495 /* Stop buffering if new queue events have arrived */
496 if (yield_codec())
497 break;
500 if (h->filerem == 0) {
501 /* finished buffering the file */
502 close(h->fd);
503 h->fd = -1;
506 DEBUGF("buffer_handle(%d): buffered %ld bytes (%ld of %ld available, "
507 "rem: %ld, off: %ld)\n",
508 handle_id, (long)ret, (long)h->available, (long)h->filesize,
509 (long)h->filerem, (long)h->offset);
511 return ret;
514 /* Reset writing position and data buffer of a handle to its current offset.
515 Use this after having set the new offset to use.
516 Returns 0 for success or -1 if the handle wasn't found. */
517 static void reset_handle(int handle_id)
519 DEBUGF("reset_handle(%d)\n", handle_id);
521 struct memory_handle *h = find_handle(handle_id);
522 if (!h)
523 return;
525 h->widx = h->data;
526 if (h == cur_handle)
527 buf_widx = h->widx;
528 h->available = 0;
529 h->filerem = h->filesize - h->offset;
531 if (h->fd >= 0) {
532 lseek(h->fd, h->offset, SEEK_SET);
536 /* Seek to a nonbuffered part of a handle by rebuffering the data. */
537 static void rebuffer_handle(int handle_id, size_t newpos)
539 struct memory_handle *h = find_handle(handle_id);
540 if (!h)
541 return;
543 DEBUGF("rebuffer_handle: resetting the handle to offset %ld\n", (long)newpos);
544 h->offset = newpos;
546 LOGFQUEUE("? >| buffering Q_RESET_HANDLE");
547 queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id);
549 LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE");
550 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
552 h->ridx = h->data;
555 static int close_handle(int handle_id)
557 struct memory_handle *h = find_handle(handle_id);
558 if (!h)
559 return -1;
561 if (h->fd >= 0) {
562 close(h->fd);
563 h->fd = -1;
566 rm_handle(h);
567 return 0;
570 /* Free buffer space by moving the handle struct right before the useful
571 part of its data buffer or by moving all the data. */
572 static void shrink_handle(int handle_id)
574 struct memory_handle *h = find_handle(handle_id);
575 if (!h)
576 return;
578 size_t delta;
579 /* The value of delta might change for alignment reasons */
581 if (h->next && (h->type == TYPE_ID3 || h->type == TYPE_CUESHEET ||
582 h->type == TYPE_IMAGE) && h->filerem == 0 )
584 /* metadata handle: we can move all of it */
585 delta = RINGBUF_SUB( (unsigned)((void *)h->next - (void *)buffer),
586 h->data) - h->available;
587 h = move_handle(h, &delta, h->available);
588 if (!h) return;
589 h->data = RINGBUF_ADD(h->data, delta);
590 h->ridx = RINGBUF_ADD(h->ridx, delta);
591 h->widx = RINGBUF_ADD(h->widx, delta);
593 /* when moving a struct mp3entry we need to readjust its pointers. */
594 if (h->type == TYPE_ID3 && h->filesize == sizeof(struct mp3entry)) {
595 adjust_mp3entry((struct mp3entry *)&buffer[h->data],
596 (void *)&buffer[h->data],
597 (void *)&buffer[RINGBUF_SUB(h->data, delta)]);
600 DEBUGF("shrink_handle(%d): metadata, moved by %ld bytes\n",
601 handle_id, (long)delta);
603 else
605 /* only move the handle struct */
606 delta = RINGBUF_SUB(h->ridx, h->data);
607 h = move_handle(h, &delta, 0);
608 if (!h) return;
609 h->data = RINGBUF_ADD(h->data, delta);
610 h->available -= delta;
611 h->offset += delta;
612 DEBUGF("shrink_handle(%d): audio, %ld bytes freed\n",
613 handle_id, (long)delta);
617 /* Fill the buffer by buffering as much data as possible for handles that still
618 have data left to buffer */
619 static void fill_buffer(void)
621 DEBUGF("fill_buffer()\n");
622 struct memory_handle *m = first_handle;
623 while (queue_empty(&buffering_queue) && m) {
624 if (m->filerem > 0) {
625 buffer_handle(m->id);
627 m = m->next;
630 #ifndef SIMULATOR
631 if (queue_empty(&buffering_queue)) {
632 /* only spin the disk down if the filling wasn't interrupted by an
633 event arriving in the queue. */
634 ata_sleep();
636 #endif
639 /* Check whether it's safe to add a new handle and reserve space to let the
640 current one finish buffering its data. Used by bufopen and bufalloc as
641 a preliminary check before even trying to physically add the handle.
642 Returns true if it's ok to add a new handle, false if not.
644 static bool can_add_handle(void)
646 if (cur_handle && cur_handle->filerem > 0) {
647 /* the current handle hasn't finished buffering. We can only add
648 a new one if there is already enough free space to finish
649 the buffering. */
650 if (cur_handle->filerem < (buffer_len - BUF_USED)) {
651 /* Before adding the new handle we reserve some space for the
652 current one to finish buffering its data. */
653 buf_widx = RINGBUF_ADD(buf_widx, cur_handle->filerem);
654 } else {
655 return false;
659 return true;
662 /* Return the total amount of data left to be buffered for all the handles */
663 static size_t data_rem(void)
665 size_t ret = 0;
667 struct memory_handle *m = first_handle;
668 while (m) {
669 ret += m->filerem;
670 m = m->next;
673 return ret;
676 /* Return the amount of data we have but don't need anymore. This data can be
677 safely erased to reclaim buffer space. */
678 static size_t wasted_space(void)
680 size_t ret = 0;
682 struct memory_handle *m = first_handle;
683 while (m) {
684 ret += RINGBUF_SUB(m->ridx, m->data);
685 m = m->next;
688 return ret;
691 static size_t buffered_data(void)
693 size_t ret = 0;
694 struct memory_handle *m = first_handle;
695 while (m) {
696 ret += m->available;
697 m = m->next;
699 return ret;
702 static size_t useful_data(void)
704 size_t ret = 0;
706 struct memory_handle *m = find_handle(base_handle_id);
707 if (!m)
708 m = first_handle;
710 while (m) {
711 ret += m->available - RINGBUF_SUB(m->ridx, m->data);
712 m = m->next;
714 return ret;
719 MAIN BUFFERING API CALLS
720 ========================
722 bufopen : Request the opening of a new handle for a file
723 bufalloc : Open a new handle for data other than a file.
724 bufclose : Close an open handle
725 bufseek : Set the read pointer in a handle
726 bufadvance : Move the read pointer in a handle
727 bufread : Copy data from a handle into a given buffer
728 bufgetdata : Give a pointer to the handle's data
730 These functions are exported, to allow interaction with the buffer.
731 They take care of the content of the structs, and rely on the linked list
732 management functions for all the actual handle management work.
736 /* Reserve space in the buffer for a file.
737 filename: name of the file to open
738 offset: offset at which to start buffering the file, useful when the first
739 (offset-1) bytes of the file aren't needed.
740 return value: <0 if the file cannot be opened, or one file already
741 queued to be opened, otherwise the handle for the file in the buffer
743 int bufopen(const char *file, size_t offset, enum data_type type)
745 if (!can_add_handle())
746 return -2;
748 int fd = open(file, O_RDONLY);
749 if (fd < 0)
750 return -1;
752 size_t size = filesize(fd) - offset;
754 if (type != TYPE_AUDIO &&
755 size + sizeof(struct memory_handle) > buffer_len - buf_widx)
757 /* for types other than audio, the data can't wrap, so we force it */
758 buf_widx = 0;
761 DEBUGF("bufopen: %s (offset: %ld) (%ld bytes needed)...\n",
762 file, (long)offset, (long)size);
764 struct memory_handle *h = add_handle(&size);
765 if (!h)
767 DEBUGF("bufopen: failed to add handle\n");
768 close(fd);
769 return -2;
772 strncpy(h->path, file, MAX_PATH);
773 h->fd = -1;
774 h->filesize = filesize(fd);
775 h->filerem = h->filesize - offset;
776 h->offset = offset;
777 h->ridx = buf_widx;
778 h->widx = buf_widx;
779 h->data = buf_widx;
780 h->available = 0;
781 h->type = type;
783 close(fd);
785 DEBUGF("bufopen: allocated %ld bytes. ID: %d\n", (long)size, h->id);
787 if (type == TYPE_CODEC || type == TYPE_CUESHEET || type == TYPE_IMAGE) {
788 /* Immediately buffer those */
789 LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE");
790 queue_send(&buffering_queue, Q_BUFFER_HANDLE, h->id);
793 DEBUGF("bufopen: opened handle %d\n", h->id);
794 return h->id;
797 /* Open a new handle from data that needs to be copied from memory.
798 src is the source buffer from which to copy data. It can be NULL to simply
799 reserve buffer space.
800 size is the requested size. The call will only be successful if the
801 requested amount of data can entirely fit in the buffer without wrapping.
802 Return value is the handle id for success or <0 for failure.
804 int bufalloc(const void *src, size_t size, enum data_type type)
806 if (!can_add_handle())
807 return -2;
809 if (size + sizeof(struct memory_handle) > buffer_len - buf_widx) {
810 /* The data would need to wrap. */
811 DEBUGF("bufalloc: data wrap\n");
812 return -2;
815 size_t allocsize = size;
816 struct memory_handle *h = add_handle(&allocsize);
818 if (!h || allocsize != size)
819 return -2;
821 if (src) {
822 if (type == TYPE_ID3 && size == sizeof(struct mp3entry)) {
823 DEBUGF("bufalloc: allocating metadata\n");
824 /* specially take care of struct mp3entry */
825 copy_mp3entry((struct mp3entry *)&buffer[buf_widx],
826 (struct mp3entry *)src);
827 } else {
828 memcpy(&buffer[buf_widx], src, size);
832 h->fd = -1;
833 *h->path = 0;
834 h->filesize = size;
835 h->filerem = 0;
836 h->offset = 0;
837 h->ridx = buf_widx;
838 h->widx = buf_widx + size; /* this is safe because the data doesn't wrap */
839 h->data = buf_widx;
840 h->available = size;
841 h->type = type;
843 buf_widx = RINGBUF_ADD(buf_widx, size);
845 DEBUGF("bufalloc: opened handle %d\n", h->id);
846 return h->id;
849 /* Close the handle. Return 0 for success and < 0 for failure */
850 int bufclose(int handle_id)
852 DEBUGF("bufclose(%d)\n", handle_id);
854 LOGFQUEUE("buffering >| Q_CLOSE_HANDLE");
855 return queue_send(&buffering_queue, Q_CLOSE_HANDLE, handle_id);
858 /* Set reading index in handle (relatively to the start of the file).
859 Access before the available data will trigger a rebuffer.
860 Return 0 for success and < 0 for failure:
861 -1 if the handle wasn't found
862 -2 if the new requested position was beyond the end of the file
864 int bufseek(int handle_id, size_t newpos)
866 struct memory_handle *h = find_handle(handle_id);
867 if (!h)
868 return -1;
870 if (newpos > h->filesize) {
871 /* access beyond the end of the file */
872 return -3;
874 else if (newpos < h->offset || h->offset + h->available < newpos) {
875 /* access before or after buffered data. A rebuffer is needed. */
876 rebuffer_handle(handle_id, newpos);
878 else {
879 h->ridx = RINGBUF_ADD(h->data, newpos - h->offset);
881 return 0;
884 /* Advance the reading index in a handle (relatively to its current position).
885 Return 0 for success and < 0 for failure */
886 int bufadvance(int handle_id, off_t offset)
888 struct memory_handle *h = find_handle(handle_id);
889 if (!h)
890 return -1;
892 size_t newpos = h->offset + RINGBUF_SUB(h->ridx, h->data) + offset;
893 return bufseek(handle_id, newpos);
896 /* Copy data from the given handle to the dest buffer.
897 Return the number of bytes copied or < 0 for failure. */
898 ssize_t bufread(int handle_id, size_t size, void *dest)
900 struct memory_handle *h = find_handle(handle_id);
901 if (!h)
902 return -1;
904 size_t ret;
905 size_t copy_n = RINGBUF_SUB(h->widx, h->ridx);
907 if (size == 0 && h->filerem > 0 && copy_n == 0)
908 /* Data isn't ready */
909 return -2;
911 if (copy_n < size && h->filerem > 0)
912 /* Data isn't ready */
913 return -2;
915 if (copy_n == 0 && h->filerem == 0)
916 /* File is finished reading */
917 return 0;
919 ret = MIN(size, copy_n);
921 if (h->ridx + ret > buffer_len)
923 /* the data wraps around the end of the buffer */
924 size_t read = buffer_len - h->ridx;
925 memcpy(dest, &buffer[h->ridx], read);
926 memcpy(dest+read, buffer, ret - read);
928 else
930 memcpy(dest, &buffer[h->ridx], ret);
933 return ret;
936 /* Update the "data" pointer to make the handle's data available to the caller.
937 Return the length of the available linear data or < 0 for failure.
938 size is the amount of linear data requested. it can be 0 to get as
939 much as possible.
940 The guard buffer may be used to provide the requested size */
941 ssize_t bufgetdata(int handle_id, size_t size, void **data)
943 struct memory_handle *h = find_handle(handle_id);
944 if (!h)
945 return -1;
947 ssize_t ret;
948 size_t copy_n = RINGBUF_SUB(h->widx, h->ridx);
950 if (size == 0 && h->filerem > 0 && copy_n == 0)
951 /* Data isn't ready */
952 return -2;
954 if (copy_n < size && h->filerem > 0)
955 /* Data isn't ready */
956 return -2;
958 if (copy_n == 0 && h->filerem == 0)
959 /* File is finished reading */
960 return 0;
962 if (h->ridx + size > buffer_len && copy_n >= size)
964 /* the data wraps around the end of the buffer :
965 use the guard buffer to provide the requested amount of data. */
966 size_t copy_n = MIN(h->ridx + size - buffer_len, GUARD_BUFSIZE);
967 memcpy(guard_buffer, (unsigned char *)buffer, copy_n);
968 ret = buffer_len - h->ridx + copy_n;
970 else
972 ret = MIN(copy_n, buffer_len - h->ridx);
975 *data = &buffer[h->ridx];
976 return ret;
980 SECONDARY EXPORTED FUNCTIONS
981 ============================
983 buf_get_offset
984 buf_handle_offset
985 buf_request_buffer_handle
986 buf_set_base_handle
987 buf_used
988 register_buffer_low_callback
989 unregister_buffer_low_callback
991 These functions are exported, to allow interaction with the buffer.
992 They take care of the content of the structs, and rely on the linked list
993 management functions for all the actual handle management work.
996 /* Get a handle offset from a pointer */
997 ssize_t buf_get_offset(int handle_id, void *ptr)
999 struct memory_handle *h = find_handle(handle_id);
1000 if (!h)
1001 return -1;
1003 return (size_t)ptr - (size_t)&buffer[h->ridx];
1006 ssize_t buf_handle_offset(int handle_id)
1008 struct memory_handle *h = find_handle(handle_id);
1009 if (!h)
1010 return -1;
1011 return h->offset;
1014 void buf_request_buffer_handle(int handle_id)
1016 LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE");
1017 queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id);
1020 void buf_set_base_handle(int handle_id)
1022 LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE");
1023 queue_post(&buffering_queue, Q_BASE_HANDLE, handle_id);
1026 /* Return the amount of buffer space used */
1027 size_t buf_used(void)
1029 return BUF_USED;
1032 bool register_buffer_low_callback(buffer_low_callback func)
1034 int i;
1035 if (buffer_callback_count >= MAX_BUF_CALLBACKS)
1036 return false;
1037 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1039 if (buffer_low_callback_funcs[i] == NULL)
1041 buffer_low_callback_funcs[i] = func;
1042 buffer_callback_count++;
1043 return true;
1045 else if (buffer_low_callback_funcs[i] == func)
1046 return true;
1048 return false;
1051 void unregister_buffer_low_callback(buffer_low_callback func)
1053 int i;
1054 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1056 if (buffer_low_callback_funcs[i] == func)
1058 buffer_low_callback_funcs[i] = NULL;
1059 buffer_callback_count--;
1062 return;
1065 static void call_buffer_low_callbacks(void)
1067 int i;
1068 for (i = 0; i < MAX_BUF_CALLBACKS; i++)
1070 if (buffer_low_callback_funcs[i])
1072 buffer_low_callback_funcs[i]();
1073 buffer_low_callback_funcs[i] = NULL;
1074 buffer_callback_count--;
1079 void buffering_thread(void)
1081 struct queue_event ev;
1083 while (true)
1085 queue_wait_w_tmo(&buffering_queue, &ev, HZ/2);
1087 switch (ev.id)
1089 case Q_BUFFER_HANDLE:
1090 LOGFQUEUE("buffering < Q_BUFFER_HANDLE");
1091 queue_reply(&buffering_queue, 1);
1092 buffer_handle((int)ev.data);
1093 break;
1095 case Q_RESET_HANDLE:
1096 LOGFQUEUE("buffering < Q_RESET_HANDLE");
1097 queue_reply(&buffering_queue, 1);
1098 reset_handle((int)ev.data);
1099 break;
1101 case Q_CLOSE_HANDLE:
1102 LOGFQUEUE("buffering < Q_CLOSE_HANDLE");
1103 queue_reply(&buffering_queue, close_handle((int)ev.data));
1104 break;
1106 case Q_BASE_HANDLE:
1107 LOGFQUEUE("buffering < Q_BASE_HANDLE");
1108 base_handle_id = (int)ev.data;
1109 break;
1111 #ifndef SIMULATOR
1112 case SYS_USB_CONNECTED:
1113 LOGFQUEUE("buffering < SYS_USB_CONNECTED");
1114 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1115 usb_wait_for_disconnect(&buffering_queue);
1116 break;
1117 #endif
1119 case SYS_TIMEOUT:
1120 LOGFQUEUE_SYS_TIMEOUT("buffering < SYS_TIMEOUT");
1121 break;
1124 /* If the buffer is low, call the callbacks to get new data */
1125 if (num_handles > 0 && useful_data() < conf_watermark)
1127 call_buffer_low_callbacks();
1130 /* If the disk is spinning, take advantage by filling the buffer */
1131 if (ata_disk_is_active() && queue_empty(&buffering_queue) &&
1132 (data_rem() > 0) && (buffered_data() < high_watermark))
1134 fill_buffer();
1137 if (ev.id == SYS_TIMEOUT && queue_empty(&buffering_queue))
1139 if (data_rem() > 0 && wasted_space() > buffered_data()/2)
1141 /* free buffer from outdated audio data */
1142 struct memory_handle *m = first_handle;
1143 while (m) {
1144 if (m->type == TYPE_AUDIO)
1145 shrink_handle(m->id);
1146 m = m->next;
1149 /* free buffer by moving metadata */
1150 m = first_handle;
1151 while (m) {
1152 if (m->type != TYPE_AUDIO)
1153 shrink_handle(m->id);
1154 m = m->next;
1159 if (data_rem() > 0 && buffered_data() < conf_watermark)
1161 fill_buffer();
1167 /* Initialise the buffering subsystem */
1168 bool buffering_init(char *buf, size_t buflen)
1170 if (!buf || !buflen)
1171 return false;
1173 buffer = buf;
1174 buffer_len = buflen;
1175 guard_buffer = buf + buflen;
1177 buf_widx = 0;
1178 buf_ridx = 0;
1180 first_handle = NULL;
1181 num_handles = 0;
1183 buffer_callback_count = 0;
1184 memset(buffer_low_callback_funcs, 0, sizeof(buffer_low_callback_funcs));
1186 mutex_init(&llist_mutex);
1188 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
1189 conf_watermark = AUDIO_DEFAULT_WATERMARK;
1191 /* Set the high watermark as 75% full...or 25% empty :) */
1192 #if MEM > 8
1193 high_watermark = 3*buflen / 4;
1194 #endif
1196 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
1197 sizeof(buffering_stack), 0,
1198 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
1199 IF_COP(, CPU));
1201 queue_init(&buffering_queue, true);
1202 queue_enable_queue_send(&buffering_queue, &buffering_queue_sender_list);
1204 return true;
1207 void buffering_get_debugdata(struct buffering_debug *dbgdata)
1209 dbgdata->num_handles = num_handles;
1210 dbgdata->data_rem = data_rem();
1211 dbgdata->wasted_space = wasted_space();
1212 dbgdata->buffered_data = buffered_data();
1213 dbgdata->useful_data = useful_data();