1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
25 #include "buffering.h"
44 #include "mp3_playback.h"
52 #include "ata_idle_notify.h"
55 #define ata_disk_is_active() 1
59 #define GUARD_BUFSIZE (32*1024)
61 #define GUARD_BUFSIZE (8*1024)
65 /* macros to enable logf for queues
66 logging on SYS_TIMEOUT can be disabled */
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 */
74 #ifdef BUFFERING_LOGQUEUES
75 #define LOGFQUEUE logf
77 #define LOGFQUEUE(...)
80 #ifdef BUFFERING_LOGQUEUES_SYS_TIMEOUT
81 #define LOGFQUEUE_SYS_TIMEOUT logf
83 #define LOGFQUEUE_SYS_TIMEOUT(...)
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 */
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 */
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 */
130 static size_t high_watermark
= 0; /* High watermark for rebuffer */
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 /* Handle cache (makes find_handle faster).
142 These need to be global so that move_handle can invalidate them. */
143 static int cached_handle_id
= -1;
144 static struct memory_handle
*cached_handle
= NULL
;
148 LINKED LIST MANAGEMENT
149 ======================
151 add_handle : Add a handle to the list
152 rm_handle : Remove a handle from the list
153 find_handle : Get a handle pointer from an ID
154 move_handle : Move a handle in the buffer (with or without its data)
156 These functions only handle the linked list structure. They don't touch the
157 contents of the struct memory_handle headers. They also change the buf_*idx
158 pointers when necessary and manage the handle IDs.
160 The first and current (== last) handle are kept track of.
161 A new handle is added at buf_widx and becomes the current one.
162 buf_widx always points to the current writing position for the current handle
163 buf_ridx always points to the location of the first handle.
164 buf_ridx == buf_widx means the buffer is empty.
168 /* Add a new handle to the linked list and return it. It will have become the
169 new current handle. The handle will reserve "data_size" bytes or if that's
170 not possible, decrease "data_size" to allow adding the handle. */
171 static struct memory_handle
*add_handle(size_t *data_size
)
173 /* this will give each handle a unique id */
174 static int cur_handle_id
= 1;
176 /* make sure buf_widx is 32-bit aligned so that the handle struct is,
177 but before that we check we can actually align. */
178 if (RINGBUF_ADD_CROSS(buf_widx
, 3, buf_ridx
) >= 0) {
181 buf_widx
= (RINGBUF_ADD(buf_widx
, 3)) & ~3;
183 size_t len
= (data_size
? *data_size
: 0)
184 + sizeof(struct memory_handle
);
186 /* check that we actually can add the handle and its data */
187 int overlap
= RINGBUF_ADD_CROSS(buf_widx
, len
, buf_ridx
);
189 *data_size
-= overlap
;
192 if (len
< sizeof(struct memory_handle
)) {
193 /* There isn't even enough space to write the struct */
197 struct memory_handle
*new_handle
=
198 (struct memory_handle
*)(&buffer
[buf_widx
]);
200 /* only advance the buffer write index of the size of the struct */
201 buf_widx
= RINGBUF_ADD(buf_widx
, sizeof(struct memory_handle
));
204 /* the new handle is the first one */
205 first_handle
= new_handle
;
209 cur_handle
->next
= new_handle
;
212 cur_handle
= new_handle
;
213 cur_handle
->id
= cur_handle_id
++;
214 cur_handle
->next
= NULL
;
219 /* Delete a given memory handle from the linked list
220 and return true for success. Nothing is actually erased from memory. */
221 static bool rm_handle(struct memory_handle
*h
)
223 if (h
== first_handle
) {
224 first_handle
= h
->next
;
225 if (h
== cur_handle
) {
226 /* h was the first and last handle: the buffer is now empty */
230 /* update buf_ridx to point to the new first handle */
231 buf_ridx
= (void *)first_handle
- (void *)buffer
;
234 struct memory_handle
*m
= first_handle
;
235 while (m
&& m
->next
!= h
) {
238 if (h
&& m
&& m
->next
== h
) {
240 if (h
== cur_handle
) {
242 buf_widx
= cur_handle
->widx
;
253 /* Return a pointer to the memory handle of given ID.
254 NULL if the handle wasn't found */
255 static struct memory_handle
*find_handle(int handle_id
)
257 /* simple caching because most of the time the requested handle
258 will either be the same as the last, or the one after the last */
261 if (cached_handle_id
== handle_id
&&
262 cached_handle_id
== cached_handle
->id
)
263 return cached_handle
;
264 else if (cached_handle
->next
&& (cached_handle
->next
->id
== handle_id
))
266 /* JD's quick testing showd this block was only entered
267 2/1971 calls to find_handle.
268 8/1971 calls to find_handle resulted in a cache miss */
269 cached_handle
= cached_handle
->next
;
270 cached_handle_id
= handle_id
;
271 return cached_handle
;
275 struct memory_handle
*m
= first_handle
;
276 while (m
&& m
->id
!= handle_id
) {
279 cached_handle_id
= handle_id
;
281 return (m
&& m
->id
== handle_id
) ? m
: NULL
;
284 /* Move a memory handle and data_size of its data of delta.
285 Return a pointer to the new location of the handle.
286 delta is the value of which to move the struct data.
287 data_size is the amount of data to move along with the struct. */
288 static struct memory_handle
*move_handle(struct memory_handle
*h
,
289 size_t *delta
, size_t data_size
)
292 /* aligning backwards would yield a negative result,
293 and moving the handle of such a small amount is a waste
297 /* make sure delta is 32-bit aligned so that the handle struct is. */
298 *delta
= (*delta
- 3) & ~3;
300 size_t newpos
= RINGBUF_ADD((void *)h
- (void *)buffer
, *delta
);
302 struct memory_handle
*dest
= (struct memory_handle
*)(&buffer
[newpos
]);
304 /* Invalidate the cache to prevent it from keeping the old location of h */
305 if (h
== cached_handle
)
306 cached_handle
= NULL
;
308 /* the cur_handle pointer might need updating */
309 if (h
== cur_handle
) {
313 if (h
== first_handle
) {
317 struct memory_handle
*m
= first_handle
;
318 while (m
&& m
->next
!= h
) {
321 if (h
&& m
&& m
->next
== h
) {
328 memmove(dest
, h
, sizeof(struct memory_handle
) + data_size
);
335 BUFFER SPACE MANAGEMENT
336 =======================
338 yield_codec : Used by buffer_handle to know if it should interrupt buffering
339 buffer_handle : Buffer data for a handle
340 reset_handle : Reset writing position and data buffer of a handle to its
342 rebuffer_handle : Seek to a nonbuffered part of a handle by rebuffering the data
343 shrink_handle : Free buffer space by moving a handle
344 fill_buffer : Call buffer_handle for all handles that have data to buffer
345 can_add_handle : Indicate whether it's safe to add a handle
346 data_rem : Total amount of data needing to be buffered
347 wasted_space : Total amount of space available for freeing
348 buffered_data : Total amount of data currently in the buffer
350 These functions are used by the buffering thread to manage buffer space.
353 /* Buffer data for the given handle. Return when finished or when an event was
354 received on the buffering queue.
355 ev is where queue events will be received. If buffering wasn't interrupted,
356 ev->id == SYS_TIMEOUT.
357 Return value is the amount of data buffered, or -1 if the handle wasn't found
359 static ssize_t
buffer_handle(int handle_id
, struct queue_event
*ev
)
361 DEBUGF("buffer_handle(%d)\n", handle_id
);
362 struct memory_handle
*h
= find_handle(handle_id
);
366 if (h
->filerem
== 0) {
367 /* nothing left to buffer */
371 if (h
->fd
< 0) /* file closed, reopen */
374 h
->fd
= open(h
->path
, O_RDONLY
);
382 lseek(h
->fd
, h
->offset
, SEEK_SET
);
388 while (h
->filerem
> 0)
390 /* max amount to copy */
391 size_t copy_n
= MIN( MIN(h
->filerem
, conf_filechunk
),
392 buffer_len
- h
->widx
);
394 /* stop copying if it would overwrite the reading position
395 or the next handle */
396 if (RINGBUF_ADD_CROSS(h
->widx
, copy_n
, buf_ridx
) >= 0 || (h
->next
&&
397 RINGBUF_ADD_CROSS(h
->widx
, copy_n
, (unsigned)
398 ((void *)h
->next
- (void *)buffer
)) > 0))
401 /* rc is the actual amount read */
402 int rc
= read(h
->fd
, &buffer
[h
->widx
], copy_n
);
406 if (h
->type
== TYPE_CODEC
) {
407 DEBUGF("Partial codec\n");
411 DEBUGF("File ended %ld bytes early\n", (long)h
->filerem
);
412 h
->filesize
-= h
->filerem
;
418 h
->widx
= RINGBUF_ADD(h
->widx
, rc
);
425 /* DEBUGF("buffer_handle(%d): buffered %ld bytes. done: %ld. remaining: %ld.\n",
426 h->id, rc, h->available, h->filerem); */
428 /* Sleep a bit and stop buffering if new queue events have arrived */
429 queue_wait_w_tmo(&buffering_queue
, ev
, 10);
431 if (ev
->id
== Q_BUFFER_HANDLE
&& (int)ev
->data
== handle_id
) {
432 /* Don't stop buffering if the request is to buffer the same file */
433 LOGFQUEUE("buffering < Q_BUFFER_HANDLE");
434 DEBUGF("buffer_handle: continuing buffering of handle %d\n",
437 else if (ev
->id
!= SYS_TIMEOUT
) {
438 /* An event was received, break the loop so it can be treated */
439 DEBUGF("buffer_handle: event received, interrupting buffering\n");
444 if (h
->filerem
== 0) {
445 /* finished buffering the file */
450 DEBUGF("buffer_handle(%d): buffered %ld bytes (%ld of %ld available, "
451 "rem: %ld, off: %ld)\n",
452 handle_id
, (long)ret
, (long)h
->available
, (long)h
->filesize
,
453 (long)h
->filerem
, (long)h
->offset
);
458 /* Reset writing position and data buffer of a handle to its current offset.
459 Use this after having set the new offset to use.
460 Returns 0 for success or -1 if the handle wasn't found. */
461 static void reset_handle(int handle_id
)
463 DEBUGF("reset_handle(%d)\n", handle_id
);
465 struct memory_handle
*h
= find_handle(handle_id
);
473 h
->filerem
= h
->filesize
- h
->offset
;
476 lseek(h
->fd
, h
->offset
, SEEK_SET
);
480 /* Seek to a nonbuffered part of a handle by rebuffering the data. */
481 static void rebuffer_handle(int handle_id
, size_t newpos
)
483 struct memory_handle
*h
= find_handle(handle_id
);
487 DEBUGF("rebuffer_handle: resetting the handle to offset %ld\n", (long)newpos
);
490 LOGFQUEUE("? >| buffering Q_RESET_HANDLE");
491 queue_send(&buffering_queue
, Q_RESET_HANDLE
, handle_id
);
493 LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE");
494 queue_send(&buffering_queue
, Q_BUFFER_HANDLE
, handle_id
);
499 /* Free buffer space by moving the handle struct right before the useful
500 part of its data buffer or by moving all the data. */
501 static void shrink_handle(int handle_id
)
503 struct memory_handle
*h
= find_handle(handle_id
);
508 /* The value of delta might change for alignment reasons */
510 if (h
->next
&& (h
->type
== TYPE_ID3
|| h
->type
== TYPE_CUESHEET
||
511 h
->type
== TYPE_IMAGE
) && h
->filerem
== 0 )
513 /* metadata handle: we can move all of it */
514 delta
= RINGBUF_SUB( (unsigned)((void *)h
->next
- (void *)buffer
),
515 h
->data
) - h
->available
;
516 h
= move_handle(h
, &delta
, h
->available
);
518 h
->data
= RINGBUF_ADD(h
->data
, delta
);
519 h
->ridx
= RINGBUF_ADD(h
->ridx
, delta
);
520 h
->widx
= RINGBUF_ADD(h
->widx
, delta
);
522 /* when moving a struct mp3entry we need to readjust its pointers. */
523 if (h
->type
== TYPE_ID3
&& h
->filesize
== sizeof(struct mp3entry
)) {
524 adjust_mp3entry((struct mp3entry
*)&buffer
[h
->data
],
525 (void *)&buffer
[h
->data
],
526 (void *)&buffer
[RINGBUF_SUB(h
->data
, delta
)]);
529 DEBUGF("shrink_handle(%d): metadata, moved by %ld bytes\n",
530 handle_id
, (long)delta
);
534 /* only move the handle struct */
535 delta
= RINGBUF_SUB(h
->ridx
, h
->data
);
536 h
= move_handle(h
, &delta
, 0);
538 h
->data
= RINGBUF_ADD(h
->data
, delta
);
539 h
->available
-= delta
;
541 DEBUGF("shrink_handle(%d): audio, %ld bytes freed\n",
542 handle_id
, (long)delta
);
546 /* Fill the buffer by buffering as much data as possible for handles that still
547 have data left to buffer */
548 static void fill_buffer(struct queue_event
*ev
)
550 DEBUGF("fill buffer()\n");
551 struct memory_handle
*m
= first_handle
;
553 if (m
->filerem
> 0) {
554 buffer_handle(m
->id
, ev
);
555 if (ev
->id
!= SYS_TIMEOUT
)
562 /* Check whether it's safe to add a new handle and reserve space to let the
563 current one finish buffering its data. Used by bufopen and bufalloc as
564 a preliminary check before even trying to physically add the handle.
565 Returns true if it's ok to add a new handle, false if not.
567 static bool can_add_handle(void)
569 if (cur_handle
&& cur_handle
->filerem
> 0) {
570 /* the current handle hasn't finished buffering. We can only add
571 a new one if there is already enough free space to finish
573 if (cur_handle
->filerem
< (buffer_len
- BUF_USED
)) {
574 /* Before adding the new handle we reserve some space for the
575 current one to finish buffering its data. */
576 buf_widx
= RINGBUF_ADD(buf_widx
, cur_handle
->filerem
);
585 /* Return the total amount of data left to be buffered for all the handles */
586 static size_t data_rem(void)
590 struct memory_handle
*m
= first_handle
;
599 /* Return the amount of data we have but don't need anymore. This data can be
600 safely erased to reclaim buffer space. */
601 static size_t wasted_space(void)
605 struct memory_handle
*m
= first_handle
;
607 ret
+= RINGBUF_SUB(m
->ridx
, m
->data
);
614 static size_t buffered_data(void)
617 struct memory_handle
*m
= first_handle
;
627 BUFFERING API FUNCTIONS
628 =======================
630 bufopen : Request the opening of a new handle for a file
631 bufalloc : Open a new handle for data other than a file.
632 bufclose : Close an open handle
633 bufseek : Set the read pointer in a handle
634 bufadvance : Move the read pointer in a handle
635 bufread : Copy data from a handle into a given buffer
636 bufgetdata : Give a pointer to the handle's data
637 bufused : Return the amount of buffer space used
639 These functions are exported, to allow interaction with the buffer.
640 They take care of the content of the structs, and rely on the linked list
641 management functions for all the actual handle management work.
645 /* Reserve space in the buffer for a file.
646 filename : name of the file to open
647 offset : offset at which to start buffering the file, useful when the first
648 (offset-1) bytes of the file aren't needed.
649 returns : <0 if the file cannot be opened, or one file already
650 queued to be opened, otherwise the handle for the file in the buffer
652 int bufopen(char *file
, size_t offset
, enum data_type type
)
654 if (!can_add_handle())
657 int fd
= open(file
, O_RDONLY
);
661 size_t size
= filesize(fd
) - offset
;
663 if (type
!= TYPE_AUDIO
&&
664 size
+ sizeof(struct memory_handle
) > buffer_len
- buf_widx
)
666 /* for types other than audio, the data can't wrap, so we force it */
670 DEBUGF("bufopen: %s (offset: %ld) (%ld bytes needed)...\n",
671 file
, (long)offset
, (long)size
);
673 struct memory_handle
*h
= add_handle(&size
);
676 DEBUGF("bufopen: failed to add handle\n");
681 strncpy(h
->path
, file
, MAX_PATH
);
683 h
->filesize
= filesize(fd
);
684 h
->filerem
= h
->filesize
- offset
;
694 DEBUGF("bufopen: allocated %ld bytes. ID: %d\n", (long)size
, h
->id
);
696 if (type
== TYPE_CODEC
|| type
== TYPE_CUESHEET
|| type
== TYPE_IMAGE
) {
697 /* Immediately buffer those */
698 LOGFQUEUE("? >| buffering Q_BUFFER_HANDLE");
699 queue_send(&buffering_queue
, Q_BUFFER_HANDLE
, h
->id
);
702 DEBUGF("bufopen: opened handle %d\n", h
->id
);
706 /* Open a new handle from data that needs to be copied from memory.
707 src is the source buffer from which to copy data. It can be NULL to simply
708 reserve buffer space.
709 size is the requested size. The call will only be successful if the
710 requested amount of data can entirely fit in the buffer without wrapping.
711 Return value is the handle id for success or <0 for failure.
713 int bufalloc(void *src
, size_t size
, enum data_type type
)
715 if (!can_add_handle())
718 if (size
+ sizeof(struct memory_handle
) > buffer_len
- buf_widx
) {
719 /* The data would need to wrap. */
720 DEBUGF("bufalloc: data wrap\n");
724 size_t allocsize
= size
;
725 struct memory_handle
*h
= add_handle(&allocsize
);
727 if (!h
|| allocsize
!= size
)
731 if (type
== TYPE_ID3
&& size
== sizeof(struct mp3entry
)) {
732 DEBUGF("bufalloc: allocating metadata\n");
733 /* specially take care of struct mp3entry */
734 copy_mp3entry((struct mp3entry
*)&buffer
[buf_widx
],
735 (struct mp3entry
*)src
);
737 memcpy(&buffer
[buf_widx
], src
, size
);
752 buf_widx
= RINGBUF_ADD(buf_widx
, size
);
754 DEBUGF("bufalloc: opened handle %d\n", h
->id
);
758 /* Close the handle. Return 0 for success and < 0 for failure */
759 int bufclose(int handle_id
)
761 DEBUGF("bufclose(%d)\n", handle_id
);
762 struct memory_handle
*h
= find_handle(handle_id
);
775 /* Set reading index in handle (relatively to the start of the file).
776 Access before the available data will trigger a rebuffer.
777 Return 0 for success and < 0 for failure:
778 -1 if the handle wasn't found
779 -2 if the new requested position was beyond the end of the file
781 int bufseek(int handle_id
, size_t newpos
)
783 struct memory_handle
*h
= find_handle(handle_id
);
787 if (newpos
> h
->filesize
) {
788 /* access beyond the end of the file */
791 else if (newpos
< h
->offset
|| h
->offset
+ h
->available
< newpos
) {
792 /* access before or after buffered data. A rebuffer is needed. */
793 rebuffer_handle(handle_id
, newpos
);
796 h
->ridx
= RINGBUF_ADD(h
->data
, newpos
- h
->offset
);
801 /* Advance the reading index in a handle (relatively to its current position).
802 Return 0 for success and < 0 for failure */
803 int bufadvance(int handle_id
, off_t offset
)
805 struct memory_handle
*h
= find_handle(handle_id
);
809 size_t newpos
= h
->offset
+ RINGBUF_SUB(h
->ridx
, h
->data
) + offset
;
811 return bufseek(handle_id
, newpos
);
814 /* Copy data from the given handle to the dest buffer.
815 Return the number of bytes copied or < 0 for failure. */
816 ssize_t
bufread(int handle_id
, size_t size
, void *dest
)
818 struct memory_handle
*h
= find_handle(handle_id
);
819 size_t buffered_data
;
823 if (size
== 0 && h
->filerem
> 0 &&
824 h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) == 0)
825 /* Data isn't ready */
828 if (h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) < size
&& h
->filerem
> 0)
829 /* Data isn't ready */
832 if (h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) == 0 && h
->filerem
== 0)
833 /* File is finished reading */
836 buffered_data
= MIN(size
, h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
));
838 if (h
->ridx
+ buffered_data
> buffer_len
)
840 /* the data wraps around the end of the buffer */
841 size_t read
= buffer_len
- h
->ridx
;
842 memcpy(dest
, &buffer
[h
->ridx
], read
);
843 memcpy(dest
+read
, buffer
, buffered_data
- read
);
845 else memcpy(dest
, &buffer
[h
->ridx
], buffered_data
);
847 return buffered_data
;
850 /* Update the "data" pointer to make the handle's data available to the caller.
851 Return the length of the available linear data or < 0 for failure.
852 size is the amount of linear data requested. it can be 0 to get as
854 The guard buffer may be used to provide the requested size */
855 ssize_t
bufgetdata(int handle_id
, size_t size
, void **data
)
857 struct memory_handle
*h
= find_handle(handle_id
);
861 if (size
== 0 && h
->filerem
> 0 &&
862 h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) == 0)
863 /* Data isn't ready */
866 if (h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) < size
&& h
->filerem
> 0)
867 /* Data isn't ready */
870 if (h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) == 0 && h
->filerem
== 0)
871 /* File is finished reading */
876 if (h
->ridx
+ size
> buffer_len
&&
877 h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
) >= size
)
879 /* the data wraps around the end of the buffer :
880 use the guard buffer to provide the requested amount of data. */
881 size_t copy_n
= MIN(h
->ridx
+ size
- buffer_len
, GUARD_BUFSIZE
);
882 memcpy(guard_buffer
, (unsigned char *)buffer
, copy_n
);
883 ret
= buffer_len
- h
->ridx
+ copy_n
;
884 DEBUGF("used the guard buffer to complete\n");
888 ret
= MIN(h
->available
- RINGBUF_SUB(h
->ridx
, h
->data
),
889 buffer_len
- h
->ridx
);
892 *data
= &buffer
[h
->ridx
];
894 /* DEBUGF("bufgetdata(%d): h->ridx=%ld, ret=%ld\n", handle_id,
895 (long)h->ridx, ret); */
899 /* Return the amount of buffer space used */
905 /* Initialise the buffering subsystem */
906 bool buffering_init(char *filebuf
, size_t filebuflen
)
908 if (!filebuf
|| !filebuflen
)
912 buffer_len
= filebuflen
;
913 guard_buffer
= buffer
+ buffer_len
;
921 conf_filechunk
= AUDIO_DEFAULT_FILECHUNK
;
922 conf_watermark
= AUDIO_DEFAULT_WATERMARK
;
924 /* Set the high watermark as 75% full...or 25% empty :) */
926 high_watermark
= 3*filebuflen
/ 4;
929 queue_init(&buffering_queue
, true);
930 queue_enable_queue_send(&buffering_queue
, &buffering_queue_sender_list
);
936 /* we dont want this rebuffering on targets with little ram
937 because the disk may never spin down */
938 static bool ata_fillbuffer_callback(void)
940 queue_post(&buffering_queue
, Q_BUFFERING_FILL_BUFFER_IF_ACTIVE_ATA
, 0);
945 void buffering_thread(void)
947 struct queue_event ev
;
951 queue_wait_w_tmo(&buffering_queue
, &ev
, HZ
/2);
954 if ((ev
.id
== SYS_TIMEOUT
) && (buffered_data() < high_watermark
))
955 register_ata_idle_func(ata_fillbuffer_callback
);
961 case Q_BUFFER_HANDLE
:
962 LOGFQUEUE("buffering < Q_BUFFER_HANDLE");
963 queue_reply(&buffering_queue
, 1);
964 buffer_handle((int)ev
.data
, &ev
);
965 /* ev is now an event received by buffer_handle() */
970 LOGFQUEUE("buffering < Q_RESET_HANDLE");
971 queue_reply(&buffering_queue
, 1);
972 reset_handle((int)ev
.data
);
977 case Q_BUFFERING_FILL_BUFFER_IF_ACTIVE_ATA
:
978 /* only fill if the disk is still spining */
980 if (!ata_disk_is_active())
983 if (num_handles
> 0 && data_rem() > 0) {
991 case SYS_USB_CONNECTED
:
992 LOGFQUEUE("buffering < SYS_USB_CONNECTED");
993 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
994 usb_wait_for_disconnect(&buffering_queue
);
999 LOGFQUEUE_SYS_TIMEOUT("buffering < SYS_TIMEOUT");
1003 if (queue_empty(&buffering_queue
) &&
1004 data_rem() > 0 && wasted_space() > buffered_data()/2) {
1005 DEBUGF("there is %ld bytes of wasted space\n", (long)wasted_space());
1007 /* free buffer from outdated audio data */
1008 struct memory_handle
*m
= first_handle
;
1010 if (m
->type
== TYPE_AUDIO
)
1011 shrink_handle(m
->id
);
1015 /* free buffer by moving metadata */
1018 if (m
->type
!= TYPE_AUDIO
)
1019 shrink_handle(m
->id
);
1025 if (queue_empty(&buffering_queue
) &&
1026 data_rem() > 0 && buffered_data() < conf_watermark
)
1028 DEBUGF("%ld bytes left to buffer and the buffer is low\n",
1036 /* Get a buffer offset from a pointer */
1037 ssize_t
get_offset(int handle_id
, void *ptr
)
1039 struct memory_handle
*h
= find_handle(handle_id
);
1043 return (size_t)ptr
- (size_t)&buffer
[h
->ridx
];
1046 void buffering_get_debugdata(struct buffering_debug
*dbgdata
)
1048 dbgdata
->num_handles
= num_handles
;
1049 dbgdata
->data_rem
= data_rem();
1050 dbgdata
->wasted_space
= wasted_space();
1051 dbgdata
->buffered_data
= buffered_data();