Fix the warnings by using more appropriate types.
[Rockbox-MoB.git] / testplugin.c
blobeabe74e1f90baf205b70d8a987c11e4693c9ff69
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 ****************************************************************************/
21 #include "plugin.h"
23 PLUGIN_HEADER
25 struct plugin_api* rb;
27 #define GUARD_SIZE (32*1024)
29 /* amount of data to read in one read() call */
30 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
32 /* Ring buffer helper macros */
33 /* Buffer pointer (p) plus value (v), wrapped if necessary */
34 #define RINGBUF_ADD(p,v) ((p+v)<buffer_len ? p+v : p+v-buffer_len)
35 /* Buffer pointer (p) minus value (v), wrapped if necessary */
36 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+buffer_len-v)
37 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
38 #define RINGBUF_ADD_CROSS(p1,v,p2) \
39 ((p1<p2) ? (int)(p1+v)-(int)p2 : (int)(p1+v-p2)-(int)buffer_len)
40 /* Bytes available in the buffer */
41 #define BUF_USED RINGBUF_SUB(buf_widx, buf_ridx)
43 #ifdef ROCKBOX_HAS_LOGF
44 #define DEBUGF rb->logf
45 #endif
47 int num_files = 5;
48 char *files[] = { "/070623 - David Vendetta.mp3",
49 "/africanism all stars feat the hard boys - hard (bob sinclair remix).mp3",
50 "/alan_braxe__kris_menace_-_lumberjack.mp3",
51 "/Ame - Rej (A Hundred Birds Remix).mp3",
52 "/Antena - Camino del Sol (Joakim Remix).mp3" };
54 struct memory_handle {
55 int id; /* A unique ID for the handle */
56 //enum data_type type;
57 //enum data_state state;
58 char path[MAX_PATH];
59 int fd;
60 size_t data; /* Start index of the handle's data buffer */
61 size_t data_len; /* Length of the data buffer for the handle */
62 size_t ridx; /* Current read pointer, relative to the main buffer */
63 size_t widx; /* Current write pointer */
64 size_t filesize; /* File total length */
65 size_t filerem; /* Remaining bytes of file NOT in buffer */
66 size_t available; /* Available bytes to read from buffer */
67 size_t offset; /* Offset at which we started reading the file */
68 struct memory_handle *next;
72 static char *buffer;
73 static char *guard_buffer;
75 static size_t buffer_len;
76 static size_t buf_widx;
77 static size_t buf_ridx;
79 static size_t conf_filechunk;
81 /* current memory handle in the linked list. NULL when the list is empty. */
82 static struct memory_handle *cur_handle;
83 /* first memory handle in the linked list. NULL when the list is empty. */
84 static struct memory_handle *first_handle;
85 static int num_handles;
87 static void graph_view(int width);
90 /* add a new handle to the linked list and return it. It will have become the
91 new current handle. The handle will reserve "data_size" bytes or if that's
92 not possible, decrease "data_size" to allow adding the handle. */
93 static struct memory_handle *add_handle(size_t *data_size)
95 /* this will give each handle a unique id */
96 static int cur_handle_id = 1;
98 size_t len = (data_size ? *data_size : 0)
99 + sizeof(struct memory_handle);
101 /* check that we actually can add the handle and its data */
102 int overlap = RINGBUF_ADD_CROSS(buf_widx, len + 3, buf_ridx);
103 if (overlap >= 0) {
104 *data_size -= overlap;
105 len -= overlap;
107 if (len < sizeof(struct memory_handle)) {
108 return NULL;
111 /* make sure buf_widx is 32-bit aligned so that the handle struct is. */
112 buf_widx = (RINGBUF_ADD(buf_widx, 3)) & ~3;
114 struct memory_handle *new_handle = (struct memory_handle *)(buffer + buf_widx);
116 /* only advance the buffer write index of the size of the struct */
117 buf_widx = RINGBUF_ADD(buf_widx, sizeof(struct memory_handle));
119 if (!first_handle) {
120 /* the new handle is the first one */
121 first_handle = new_handle;
124 if (cur_handle) {
125 cur_handle->next = new_handle;
128 cur_handle = new_handle;
129 cur_handle->id = cur_handle_id++;
130 cur_handle->next = NULL;
131 num_handles++;
132 return cur_handle;
135 /* delete a given memory handle from the linked list
136 and return true for success. Nothing is actually erased from memory. */
137 static bool rm_handle(struct memory_handle *h)
139 if (h == first_handle) {
140 first_handle = h->next;
141 if (h == cur_handle) {
142 DEBUGF("removing the first and last handle\n");
143 /* h was the first and last handle */
144 cur_handle = NULL;
145 buf_ridx = buf_widx;
146 } else {
147 buf_ridx = (void *)first_handle - (void *)buffer;
149 } else {
150 struct memory_handle *m = first_handle;
151 while (m && m->next != h) {
152 m = m->next;
154 if (h && m && m->next == h) {
155 m->next = h->next;
156 if (h == cur_handle) {
157 cur_handle = m;
159 } else {
160 return false;
164 num_handles--;
165 return true;
168 /* these are unfortunalty needed to be global
169 so move_handle can invalidate them */
170 static int cached_handle_id = -1;
171 static struct memory_handle *cached_handle = NULL;
173 /* Return a pointer to the memory handle of given ID.
174 NULL if the handle wasn't found */
175 static struct memory_handle *find_handle(int handle_id)
177 /* simple caching because most of the time the requested handle
178 will either be the same as the last, or the one after the last */
179 if (cached_handle)
181 if (cached_handle_id == handle_id && cached_handle_id == cached_handle->id)
182 return cached_handle;
183 else if (cached_handle->next && (cached_handle->next->id == handle_id))
185 /* JD's quick testing showd this block was only entered
186 2/1971 calls to find_handle.
187 8/1971 calls to find_handle resulted in a cache miss */
188 cached_handle = cached_handle->next;
189 cached_handle_id = handle_id;
190 return cached_handle;
194 struct memory_handle *m = first_handle;
195 while (m && m->id != handle_id) {
196 m = m->next;
198 cached_handle_id = handle_id;
199 cached_handle = m;
200 return (m && m->id == handle_id) ? m : NULL;
203 /* Move a memory handle to newpos.
204 Return a pointer to the new location of the handle */
205 static struct memory_handle *move_handle(size_t newpos, struct memory_handle *h)
207 /* make sure newpos is 32-bit aligned so that the handle struct is. */
208 newpos = (RINGBUF_ADD(newpos, 3)) & ~3;
210 DEBUGF("move_handle\n");
211 struct memory_handle *dest = (struct memory_handle *)(buffer + newpos);
213 /* Invalidate the cache to prevent it from keeping the old location of h */
214 if (h == cached_handle)
215 cached_handle = NULL;
217 /* the cur_handle pointer might need updating */
218 if (h == cur_handle) {
219 cur_handle = dest;
222 if (h == first_handle) {
223 first_handle = dest;
224 buf_ridx = newpos;
225 } else {
226 struct memory_handle *m = first_handle;
227 while (m && m->next != h) {
228 m = m->next;
230 if (h && m && m->next == h) {
231 m->next = dest;
232 } else {
233 return NULL;
237 DEBUGF("h: %lx", (long)h);
238 DEBUGF("h->id: %d", h->id);
239 DEBUGF("dest: %lx", (long)dest);
240 DEBUGF("dest->id: %d", dest->id);
241 DEBUGF("memmove");
243 rb->memmove(dest, h, sizeof(struct memory_handle));
245 DEBUGF("h: %lx", (long)h);
246 DEBUGF("dest: %lx", (long)dest);
247 DEBUGF("dest->id: %d", dest->id);
249 return dest;
251 /* Buffer data for the given handle. Return the amount of data buffered
252 or -1 if the handle wasn't found */
253 static ssize_t buffer_handle(int handle_id)
255 DEBUGF("buffer_handle(%d)\n", handle_id);
256 struct memory_handle *h = find_handle(handle_id);
257 if (!h)
258 return -1;
260 if (h->filerem == 0) {
261 /* nothing left to buffer */
262 return 0;
265 if (h->fd < 0) /* file closed, reopen */
267 if (*h->path)
268 h->fd = rb->open(h->path, O_RDONLY);
269 else
270 return -1;
272 if (h->fd < 0)
273 return -1;
275 if (h->offset)
276 rb->lseek(h->fd, h->offset, SEEK_SET);
279 ssize_t ret = 0;
280 while (h->filerem > 0)
282 //DEBUGF("h: %d\n", (void *)h - (void *)buffer);
283 //DEBUGF("buf_widx: %ld\n", (long)buf_widx);
284 /* max amount to copy */
285 size_t copy_n = MIN(conf_filechunk, buffer_len - buf_widx);
287 /* stop copying if it would overwrite the reading position */
288 if (RINGBUF_ADD_CROSS(buf_widx, copy_n, buf_ridx) >= 0)
289 break;
291 /* rc is the actual amount read */
292 int rc = rb->read(h->fd, &buffer[buf_widx], copy_n);
294 if (rc < 0)
296 //DEBUGF("failed on fd %d at buf_widx = %ld for handle %d\n", h->fd, (long)buf_widx, h->id);
297 DEBUGF("File ended %ld bytes early\n", (long)h->filerem);
298 h->filesize -= h->filerem;
299 h->filerem = 0;
300 break;
303 /* Advance buffer */
304 h->widx = RINGBUF_ADD(h->widx, rc);
305 if (h == cur_handle)
306 buf_widx = h->widx;
307 h->available += rc;
308 ret += rc;
309 h->filerem -= rc;
312 if (h->filerem == 0) {
313 /* finished buffering the file */
314 rb->close(h->fd);
317 DEBUGF("buffered %ld bytes (%ld of %ld available, remaining: %ld)\n",
318 ret, h->available, h->filesize, h->filerem);
320 graph_view(100);
322 return ret;
325 /* Free buffer space by moving the first handle struct right before the useful
326 part of its data buffer */
327 static void free_buffer(int handle_id)
329 DEBUGF("free_buffer(%d)\n", handle_id);
330 struct memory_handle *h = find_handle(handle_id);
331 if (!h)
332 return;
334 size_t delta = RINGBUF_SUB(h->ridx, h->data);
335 size_t dest = RINGBUF_ADD((void *)h - (void *)buffer, delta);
336 //DEBUGF("buf_ridx: %ld, buf_widx: %ld\n", (long)buf_ridx, (long)buf_widx);
337 //DEBUGF("dest: %ld, delta: %ld\n", (long)dest, (long)delta);
338 h = move_handle(dest, h);
339 h->data = RINGBUF_ADD(h->data, delta);
340 h->ridx = h->data;
341 h->available -= delta;
343 graph_view(100);
346 static void fill_buffer(void)
348 DEBUGF("fill buffer()\n");
349 struct memory_handle *m = first_handle;
350 while (m) {
351 if (m->filerem > 0) {
352 buffer_handle(first_handle->id);
353 return;
355 m = m->next;
359 static size_t data_rem(void)
361 size_t ret = 0;
363 struct memory_handle *m = first_handle;
364 while (m) {
365 ret += m->filerem;
366 m = m->next;
369 return ret;
372 static size_t wasted_space(void)
374 size_t ret = 0;
376 struct memory_handle *m = first_handle;
377 while (m) {
378 ret += RINGBUF_SUB(m->ridx, m->data);
379 m = m->next;
382 return ret;
385 /* Request a file be buffered
386 filename: name of the file t open
387 offset: starting offset to buffer from the file
388 RETURNS: <0 if the file cannot be opened, or one file already
389 queued to be opened, otherwise the handle for the file in the buffer
391 int bufopen(char *file, size_t offset)
393 DEBUGF("bufopen: %s (offset: %ld)\n", file, offset);
395 int fd = rb->open(file, O_RDONLY);
396 if (fd < 0)
397 return -1;
399 if (offset)
400 rb->lseek(fd, offset, SEEK_SET);
402 size_t size = rb->filesize(fd) - offset;
403 struct memory_handle *h = add_handle(&size);
404 if (!h)
406 DEBUGF("failed to add handle\n");
407 return -1;
410 rb->strncpy(h->path, file, MAX_PATH);
411 h->fd = fd;
412 h->filesize = rb->filesize(fd);
413 h->filerem = h->filesize - offset;
414 h->offset = offset;
415 h->ridx = buf_widx;
416 h->widx = buf_widx;
417 h->data = buf_widx;
418 h->data_len = size;
419 h->available = 0;
421 DEBUGF("added handle : %d\n", h->id);
422 return h->id;
425 /* Close the handle. Return 0 for success and < 0 for failure */
426 int bufclose(int handle_id)
428 DEBUGF("bufclose(%d)\n", handle_id);
429 struct memory_handle *h = find_handle(handle_id);
430 if (!h)
431 return -1;
433 rm_handle(h);
434 return 0;
437 /* Set the reading index in a handle (relatively to the start of the handle data).
438 Return 0 for success and < 0 for failure */
439 int bufseek(int handle_id, size_t offset)
441 struct memory_handle *h = find_handle(handle_id);
442 if (!h)
443 return -1;
445 if (offset > h->available)
446 return -2;
448 h->ridx = RINGBUF_ADD(h->data, offset);
449 return 0;
452 /* Advance the reading index in a handle (relatively to its current position).
453 Return 0 for success and < 0 for failure */
454 int bufadvance(int handle_id, off_t offset)
456 struct memory_handle *h = find_handle(handle_id);
457 if (!h)
458 return -1;
460 if (offset >= 0)
462 /* check for access beyond what's available */
463 if ((size_t)offset > (h->available - RINGBUF_SUB(h->ridx, h->data)))
464 return -2;
466 h->ridx = RINGBUF_ADD(h->ridx, offset);
468 else
470 /* check for access before what's available */
471 if ((size_t)(-offset) > RINGBUF_SUB(h->ridx, h->data))
472 return -2;
474 h->ridx = RINGBUF_SUB(h->ridx, (size_t)(-offset));
477 return 0;
480 /* Copy data from the given handle to the dest buffer.
481 Return the number of bytes copied or < 0 for failure. */
482 ssize_t bufread(int handle_id, size_t size, char *dest)
484 struct memory_handle *h = find_handle(handle_id);
485 size_t buffered_data;
486 if (!h)
487 return -1;
489 if (h->available == 0 && h->filerem > 0)
490 return -2;
492 if (h->available == 0 && h->filerem == 0)
493 return 0;
495 buffered_data = MIN(size, h->available);
497 if (h->ridx + buffered_data > buffer_len)
499 size_t read = buffer_len - h->ridx;
500 rb->memcpy(dest, &buffer[h->ridx], read);
501 rb->memcpy(dest+read, buffer, buffered_data - read);
503 else rb->memcpy(dest, &buffer[h->ridx], buffered_data);
505 h->ridx = RINGBUF_ADD(h->ridx, buffered_data);
506 h->available -= buffered_data;
507 return buffered_data;
510 /* Update the "data" pointer to make the handle's data available to the caller.
511 Return the length of the available linear data or < 0 for failure. */
512 ssize_t bufgetdata(int handle_id, size_t size, unsigned char **data)
514 struct memory_handle *h = find_handle(handle_id);
515 if (!h)
516 return -1;
518 if (h->available == 0 && h->filerem > 0)
519 return -2;
521 if (h->available == 0 && h->filerem == 0)
522 return 0;
524 ssize_t ret;
526 if (h->ridx + size > buffer_len &&
527 h->available - RINGBUF_SUB(h->ridx, h->data) >= size)
529 /* use the guard buffer to provide what was requested. */
530 size_t copy_n = h->ridx + size - buffer_len;
531 rb->memcpy(guard_buffer, (unsigned char *)buffer, copy_n);
532 ret = size;
534 else
536 ret = MIN(h->available - RINGBUF_SUB(h->ridx, h->data),
537 buffer_len - h->ridx);
540 *data = (unsigned char *)(buffer + h->ridx);
542 //DEBUGF("bufgetdata(%d): h->ridx=%ld, ret=%ld\n", handle_id, (long)h->ridx, ret);
543 return ret;
546 bool test_ll(void)
548 struct memory_handle *m1, *m2, *m3, *m4;
550 if (cur_handle != NULL || first_handle != NULL)
551 return false;
553 m1 = add_handle(NULL);
555 if (cur_handle != m1 || first_handle != m1 || m1->next != NULL)
556 return false;
558 m2 = add_handle(NULL);
560 if (cur_handle != m2 || first_handle != m1 || m1->next != m2 || m2->next != NULL)
561 return false;
563 m3 = add_handle(NULL);
565 if (cur_handle != m3 || first_handle != m1 || m2->next != m3 || m3->next != NULL)
566 return false;
568 rm_handle(m2);
570 if (cur_handle != m3 || first_handle != m1 || m1->next != m3)
571 return false;
573 rm_handle(m3);
575 if (cur_handle != m1 || first_handle != m1 || m1->next != NULL)
576 return false;
578 m4 = add_handle(NULL);
580 if (cur_handle != m4 || first_handle != m1 || m1->next != m4 || m4->next != NULL)
581 return false;
583 rm_handle(m1);
585 if (cur_handle != m4 || first_handle != m4)
586 return false;
588 rm_handle(m4);
590 if (cur_handle != NULL || first_handle != NULL)
591 return false;
593 m1 = add_handle(NULL);
594 m2 = add_handle(NULL);
595 m3 = add_handle(NULL);
596 m4 = add_handle(NULL);
598 if (cur_handle != m4 || first_handle != m1)
599 return false;
601 #if 0
602 m2 = move_handle(RINGBUF_ADD(m2->data, 1024*100), m2);
604 if (cur_handle != m4 || first_handle != m1 || m1->next != m2 || m2->next != m3)
605 return false;
607 m1 = move_handle(RINGBUF_ADD(m1->data, 1024*100*3), m1);
609 if (cur_handle != m4 || first_handle != m1 || m1->next != m2)
610 return false;
611 #endif
613 rm_handle(m1);
614 rm_handle(m2);
615 rm_handle(m3);
616 rm_handle(m4);
618 if (cur_handle != NULL || first_handle != NULL)
619 return false;
621 return true;
624 #if 0
625 static void list_handles(void)
627 struct memory_handle *m = first_handle;
628 while (m) {
629 DEBUGF("%02d - %d\n", m->id, (void *)m-(void *)buffer);
630 m = m->next;
633 #endif
635 /* display a nice graphical view of the ringbuffer. */
636 static void graph_view(int width)
638 #ifndef ROCKBOX_HAS_LOGF
639 int i, r_pos, w_pos;
640 r_pos = buf_ridx * width / buffer_len;
641 w_pos = buf_widx * width / buffer_len;
643 DEBUGF("|");
644 for (i=0; i <= width; i++)
646 if (i != r_pos && i != w_pos)
648 if (buf_ridx <= buf_widx)
650 if (i > r_pos && i < w_pos) {
651 DEBUGF(">");
652 } else {
653 DEBUGF("-");
656 else
658 if (i > r_pos || i < w_pos) {
659 DEBUGF(">");
660 } else {
661 DEBUGF("-");
665 else
667 if (i == r_pos && i == w_pos)
669 if (buf_ridx <= buf_widx) {
670 DEBUGF("RW");
671 } else {
672 DEBUGF("WR");
674 } else if (i == r_pos) {
675 DEBUGF("R");
676 } else if (i == w_pos) {
677 DEBUGF("W");
681 DEBUGF("|");
682 DEBUGF("\n");
683 #else
684 (void)width;
685 #endif
688 bool buffer_init(void)
690 buffer = rb->plugin_get_audio_buffer(&buffer_len);
691 if (!buffer)
693 DEBUGF("couldn't allocate buffer\n");
694 return false;
696 buffer_len -= GUARD_SIZE;
697 guard_buffer = buffer + buffer_len;
699 buf_widx = 0;
700 buf_ridx = 0;
702 first_handle = NULL;
703 num_handles = 0;
705 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
707 return true;
710 #if 0
711 /* returns true if the file still has some on disk unread */
712 bool handle_has_data(int handle)
714 struct memory_handle *m = find_handle(handle);
715 if (m)
717 return m->filerem != 0;
719 return false;
722 bool need_rebuffer(void)
724 size_t free, wasted;
725 wasted = first_handle? RINGBUF_SUB(first_handle->ridx,
726 first_handle->data) : 0;
727 while (wasted > buffer_len / 2)
729 free_buffer(first_handle->id);
730 wasted = first_handle? RINGBUF_SUB(first_handle->ridx,
731 first_handle->data) : 0;
733 free = buffer_len - BUF_USED;
734 return ((free >= buffer_len/4));
736 #endif
738 bool disk_is_spinning(void)
740 return true;
745 static long playback_stack[4*DEFAULT_STACK_SIZE/sizeof(long)];
746 static struct thread_entry* playbackthread_id;
748 bool done_playing = false;
750 #if 0
751 static int handle_order[MAX_HANDLES];
752 static int last_handle = -1;
753 #endif
755 #define MAX_HANDLES 16
757 void playback_thread(void)
760 int handles[MAX_HANDLES];
761 int idx = 0;
762 int fd = -1; /* used to write the files out as they are read */
763 unsigned char *data;
764 char outfile[MAX_PATH];
765 long read, total = 0;
767 while (1)
769 if (!done_playing)
771 if (handles[idx] <= 0) {
772 handles[idx] = bufopen(files[idx], 0);
773 total = 0;
774 } else {
776 if (fd < 0) {
777 rb->snprintf(outfile, MAX_PATH, "/file%d.mp3", idx);
778 fd = rb->open(outfile, O_CREAT|O_TRUNC|O_WRONLY);
779 if (fd < 0) {
780 DEBUGF("couldn't create file\n");
781 rb->splash(HZ, "couldn't create file");
785 do {
786 read = bufgetdata(handles[idx], GUARD_SIZE, &data);
787 read = MIN(read, GUARD_SIZE);
788 rb->write(fd, data, read);
789 if (read >= 0) {
790 total += read;
791 bufadvance(handles[idx], read);
793 rb->sleep(HZ/50);
794 } while (read > 0);
796 if (read >= 0 && total >= 0) {
797 DEBUGF("read %ld bytes from handle %d\n", total, handles[idx]);
800 if (read == -2) {
801 DEBUGF("data for handle %d isn't ready\n", handles[idx]);
802 } else if (read == -1) {
803 DEBUGF("couldn't find handle %d\n", handles[idx]);
804 } else if (read == 0) {
805 DEBUGF("finished reading handle %d\n", handles[idx]);
806 bufclose(handles[idx]);
807 rb->close(fd);
808 fd = -1;
809 idx++;
811 if (idx >= num_files) {
812 done_playing = true;
813 break;
819 rb->sleep(HZ/5);
822 DEBUGF("removing the playback thread\n");
823 rb->remove_thread(NULL);
825 #if 0
826 int reading_handle = 0;
827 int fd = -1; /* used to write the files out as they are read */
828 unsigned char *data;
830 /* "Playback thread" section */
831 while (1)
833 DEBUGF("reading handle: %d\n", handle_order[reading_handle]);
834 long read;
835 long total = 0;
836 char file[MAX_PATH];
837 if (reading_handle >= last_handle
838 && !handle_has_data(handle_order[reading_handle]))
839 done_playing = true;
841 if (fd < 0)
843 rb->snprintf(file, MAX_PATH, "/file%d.mp3", reading_handle);
844 fd = rb->open(file, O_CREAT|O_TRUNC|O_WRONLY);
845 if (fd < 0)
847 DEBUGF("ERROROROROR\n");
848 rb->splash(HZ, "couldn't create file");
853 //read = bufread(handle_order[reading_handle], GUARD_SIZE,read_buffer);
854 //write(fd, read_buffer, read);
855 read = bufgetdata(handle_order[reading_handle], GUARD_SIZE, &data);
856 read = MIN(read, GUARD_SIZE);
857 rb->write(fd, data, read);
858 total += read;
859 bufadvance(handle_order[reading_handle], read);
860 rb->sleep(HZ/5);
862 while (read > 0);
864 DEBUGF("read %ld bytes from handle %d\n", total,
865 handle_order[reading_handle]);
867 /* close the fd/handle if there is no more data or an error */
868 if (read < 0 || handle_has_data(handle_order[reading_handle]) == false)
870 DEBUGF("finished reading %d\n",handle_order[reading_handle]);
871 bufclose(handle_order[reading_handle]);
872 rb->close(fd);
873 reading_handle++;
874 fd = -1;
876 else
878 DEBUGF("there is data left to buffer for %d\n",
879 handle_order[reading_handle]);
882 #endif
886 /* this is the plugin entry point */
887 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
889 (void)parameter;
890 rb = api;
892 buffer_init();
894 if (!test_ll())
896 DEBUGF("linked list test failed\n");
897 rb->splash(HZ, "linked list test failed");
898 return PLUGIN_ERROR;
901 playbackthread_id = rb->create_thread(playback_thread,
902 playback_stack,
903 sizeof(playback_stack),
904 "playback"
905 IF_PRIO(,PRIORITY_PLAYBACK)
906 IF_COP(, CPU, false));
908 if (!playbackthread_id)
910 rb->splash(HZ, "failed to create playback thread");
911 return PLUGIN_ERROR;
913 else
916 while (!done_playing)
918 if (wasted_space() > buffer_len/4) {
919 DEBUGF("there is %ld bytes of wasted space\n", wasted_space());
920 struct memory_handle *m = first_handle;
921 while (m) {
922 free_buffer(m->id);
923 m = m->next;
927 if (data_rem() > 0 && BUF_USED < buffer_len/4 && disk_is_spinning()) {
928 DEBUGF("%ld bytes left to buffer and the buffer is running low\n", data_rem());
929 fill_buffer();
930 } else {
931 rb->sleep(HZ/2);
934 DEBUGF("done playing\n");
935 rb->yield();
938 #if 0
939 int argc = 6;
940 char *argv[] = { NULL,
941 "/070623 - David Vendetta.mp3",
942 "/africanism all stars feat the hard boys - hard (bob sinclair remix).mp3",
943 "/alan_braxe__kris_menace_-_lumberjack.mp3",
944 "/Ame - Rej (A Hundred Birds Remix).mp3",
945 "/Antena - Camino del Sol (Joakim Remix).mp3" };
947 int next_file = 1;
948 int current_handle = -1;
949 struct memory_handle *m = NULL;
951 /* "Buffering thread" section */
952 if (!done_buffering && need_rebuffer() && disk_is_spinning())
954 m = find_handle(current_handle);
955 if ( !m || ((m->filerem == 0) && (m->next == NULL)))
957 int h = bufopen(argv[next_file], 0);
958 m = find_handle(h);
959 if (h >= 0)
961 next_file++;
962 //DEBUGF("new handle %d\n",h);
963 last_handle++;
964 handle_order[last_handle] = h;
965 buffer_handle(m->id);
967 else
969 DEBUGF("error\n");
971 current_handle = h;
973 else
975 if (m->filerem == 0)
977 m = m->next;
978 current_handle = m?m->id:-1;
980 if (m)
982 DEBUGF("buffering handle %d\n",m->id);
983 buffer_handle(m->id);
987 if (next_file == argc && m->filerem == 0)
988 done_buffering = true;
991 DEBUGF("buffer usage: %d handles_used: %d\n", BUF_USED,num_handles);
993 graph_view(100);
995 #endif
997 DEBUGF("end of plugin\n");
998 return PLUGIN_OK;