Part of Slepp's ProjectsPastebinTURLImagebinFilebin
Feedback -- English French German Japanese
Create Upload Newest Tools Donate
Sign In | Create Account

Miscellany
Thursday, July 5th, 2007 at 3:36:18pm UTC 

  1. /***************************************************************************
  2.  *             __________               __   ___.
  3.  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
  4.  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
  5.  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  6.  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  7.  *                     \/            \/     \/    \/            \/
  8.  * $Id$
  9.  *
  10.  * Copyright (C) 2007 Nicolas Pennequin
  11.  *
  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.
  14.  *
  15.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  16.  * KIND, either express or implied.
  17.  *
  18.  ****************************************************************************/
  19.  
  20.  
  21. #include "plugin.h"
  22.  
  23. PLUGIN_HEADER
  24.  
  25. struct plugin_api* rb;
  26.  
  27. #define GUARD_SIZE   (32*1024)
  28.  
  29. /* amount of data to read in one read() call */
  30. #define AUDIO_DEFAULT_FILECHUNK      (1024*32)
  31.  
  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)
  42.  
  43. struct memory_handle {
  44.     int id;              /* A unique ID for the handle */
  45.     //enum data_type type;
  46.     //enum data_state state;
  47.     char path[MAX_PATH];
  48.     int fd;
  49.     size_t data;         /* Start index of the handle's data buffer */
  50.     size_t ridx;         /* Current read pointer, relative to the main buffer */
  51.     size_t widx;         /* Current write pointer */
  52.     size_t filesize;     /* File total length */
  53.     size_t filerem;      /* Remaining bytes of file NOT in buffer */
  54.     size_t available;    /* Available bytes to read from buffer */
  55.     size_t offset;       /* Offset at which we started reading the file */
  56.     struct memory_handle *next;
  57. };
  58.  
  59. static char *buffer;
  60. static char *guard_buffer;
  61.  
  62. static size_t buffer_len;
  63. static size_t buf_widx;
  64. static size_t buf_ridx;
  65.  
  66. static size_t conf_filechunk;
  67.  
  68. /* current memory handle in the linked list. NULL when the list is empty. */
  69. static struct memory_handle *cur_handle;
  70. /* first memory handle in the linked list. NULL when the list is empty. */
  71. static struct memory_handle *first_handle;
  72. static int num_handles;
  73.  
  74. static void graph_view(int width);
  75.  
  76. /* add a new handle to the linked list and return it. It will have become the
  77.    new current handle */
  78. static struct memory_handle *add_handle(void)
  79. {
  80.     rb->logf("add_handle");
  81.  
  82.     /* this will give each handle a unique id */
  83.     static int cur_handle_id = 0;
  84.  
  85.     int data_size = sizeof(struct memory_handle);
  86.  
  87.     /* check that we actually can add the handle and its data */
  88.     if (RINGBUF_ADD_CROSS(buf_widx, data_size, buf_ridx) >= 0) {
  89.         return NULL;
  90.     }
  91.  
  92.     struct memory_handle *new_handle = (struct memory_handle *)(buffer + buf_widx);
  93.     buf_widx = RINGBUF_ADD(buf_widx, data_size);
  94.  
  95.     if (!first_handle) {
  96.         /* the new handle is the first one */
  97.         first_handle = new_handle;
  98.     }
  99.  
  100.     if (cur_handle) {
  101.         cur_handle->next = new_handle;
  102.     }
  103.  
  104.     cur_handle = new_handle;
  105.     rb->logf("cur_handle_id: %d", cur_handle_id);
  106.     cur_handle->id = cur_handle_id;
  107.     rb->logf("cur_handle->id: %d", cur_handle->id);
  108.     cur_handle->next = NULL;
  109.     num_handles++;
  110.     cur_handle_id++;
  111.     rb->logf("cur_handle: %lx", (unsigned long)cur_handle);
  112.     rb->logf("cur_handle->id: %d", cur_handle->id);
  113.     return cur_handle;
  114. }
  115.  
  116. /* delete a given memory handle from the linked list
  117.    and return true for success. Nothing is actually erased from memory. */
  118. static bool rm_handle(struct memory_handle *h)
  119. {
  120.     if (h == first_handle) {
  121.         first_handle = h->next;
  122.         if (h == cur_handle) {
  123.             rb->logf("removing the first and last handle\n");
  124.             cur_handle = NULL;
  125.             buf_ridx = buf_widx;
  126.         } else {
  127.             buf_ridx = (void *)first_handle - (void *)buffer;
  128.         }
  129.     } else {
  130.         struct memory_handle *m = first_handle;
  131.         while (m && m->next != h) {
  132.             m = m->next;
  133.         }
  134.         if (h && m && m->next == h) {
  135.             m->next = h->next;
  136.             if (h == cur_handle) {
  137.                 cur_handle = m;
  138.             }
  139.         } else {
  140.             return false;
  141.         }
  142.     }
  143.  
  144.     num_handles--;
  145.     return true;
  146. }
  147.  
  148. /* these are unfortunalty needed to be global
  149.     so move_handle can invalidate them */
  150. static int cached_handle_id = -1;
  151. static struct memory_handle *cached_handle = NULL;
  152.  
  153. /* Return a pointer to the memory handle of given ID.
  154.    NULL if the handle wasn't found */
  155. static struct memory_handle *find_handle(int handle_id)
  156. {
  157.     /* simple caching because most of the time the requested handle
  158.     will either be the same as the last, or the one after the last */
  159.     if (cached_handle)
  160.     {
  161.         if (cached_handle_id == handle_id && cached_handle_id == cached_handle->id)
  162.             return cached_handle;
  163.         else if (cached_handle->next && (cached_handle->next->id == handle_id))
  164.         {
  165.             /* JD's quick testing showd this block was only entered
  166.                2/1971 calls to find_handle.
  167.                8/1971 calls to find_handle resulted in a cache miss */
  168.             cached_handle = cached_handle->next;
  169.             cached_handle_id = handle_id;
  170.             return cached_handle;
  171.         }
  172.     }
  173.  
  174.     struct memory_handle *m = first_handle;
  175.     while (m && m->id != handle_id) {
  176.         m = m->next;
  177.     }
  178.     cached_handle_id = handle_id;
  179.     cached_handle = m;
  180.     return (m && m->id == handle_id) ? m : NULL;
  181. }
  182.  
  183. /* Move a memory handle to newpos.
  184.    Return a pointer to the new location of the handle */
  185. static struct memory_handle *move_handle(size_t newpos, struct memory_handle *h)
  186. {
  187.     struct memory_handle *dest = (struct memory_handle *)(buffer + newpos);
  188.  
  189.     /* Invalidate the cache to prevent it from keeping the old location of h */
  190.     if (h == cached_handle)
  191.         cached_handle = NULL;
  192.  
  193.     /* the cur_handle pointer might need updating */
  194.     if (h == cur_handle) {
  195.         cur_handle = dest;
  196.     }
  197.  
  198.     if (h == first_handle) {
  199.         first_handle = dest;
  200.         buf_ridx = newpos;
  201.     } else {
  202.         struct memory_handle *m = first_handle;
  203.         while (m && m->next != h) {
  204.             m = m->next;
  205.         }
  206.         if (h && m && m->next == h) {
  207.             m->next = dest;
  208.         } else {
  209.             return NULL;
  210.         }
  211.     }
  212.     rb->memmove(dest, h, sizeof(struct memory_handle));
  213.     return dest;
  214. }
  215. /* Buffer data for the given handle. Return the amount of data buffered
  216.    or -1 if the handle wasn't found */
  217. static int buffer_handle(int handle_id)
  218. {
  219.     rb->logf("buffer_handle(%d)", handle_id);
  220.     struct memory_handle *h = find_handle(handle_id);
  221.     if (!h)
  222.         return -1;
  223.  
  224.     if (h->filerem == 0) {
  225.         /* nothing left to buffer */
  226.         return 0;
  227.     }
  228.  
  229.     if (h->fd < 0)  /* file closed, reopen */
  230.     {
  231.         if (*h->path)
  232.             h->fd = rb->open(h->path, O_RDONLY);
  233.         else
  234.             return -1;
  235.  
  236.         if (h->fd < 0)
  237.             return -1;
  238.  
  239.         if (h->offset)
  240.             rb->lseek(h->fd, h->offset, SEEK_SET);
  241.     }
  242.  
  243.     int ret = 0;
  244.     while (h->filerem > 0)
  245.     {
  246.         //rb->logf("h: %d\n", (void *)h - (void *)buffer);
  247.         //rb->logf("buf_widx: %ld\n", (long)buf_widx);
  248.         /* max amount to copy */
  249.         size_t copy_n = MIN(conf_filechunk, buffer_len - buf_widx);
  250.  
  251.         /* stop copying if it would overwrite the reading position */
  252.         if (RINGBUF_ADD_CROSS(buf_widx, copy_n, buf_ridx) >= 0)
  253.             break;
  254.  
  255.         /* rc is the actual amount read */
  256.         int rc = rb->read(h->fd, &buffer[buf_widx], copy_n);
  257.  
  258.         if (rc < 0)
  259.         {
  260.             //rb->logf("failed on fd %d at buf_widx = %ld for handle %d\n", h->fd, (long)buf_widx, h->id);
  261.             rb->logf("File ended %ld bytes early\n", (long)h->filerem);
  262.             h->filesize -= h->filerem;
  263.             h->filerem = 0;
  264.             break;
  265.         }
  266.  
  267.         /* Advance buffer */
  268.         h->widx = RINGBUF_ADD(h->widx, rc);
  269.         if (h == cur_handle)
  270.             buf_widx = h->widx;
  271.         h->available += rc;
  272.         ret += rc;
  273.         h->filerem -= rc;
  274.     }
  275.  
  276.     if (h->filerem == 0) {
  277.         /* finished buffering the file */
  278.         rb->close(h->fd);
  279.     }
  280.  
  281.     rb->logf("buffered %d bytes (%d of %d available, remaining: %d)\n",
  282.            ret, h->available, h->filesize, h->filerem);
  283.     return ret;
  284. }
  285.  
  286. /* Free buffer space by moving the first handle struct right before the useful
  287.    part of its data buffer */
  288. static void free_buffer(int handle_id)
  289. {
  290.     rb->logf("free_buffer(%d)\n", handle_id);
  291.     struct memory_handle *h = find_handle(handle_id);
  292.     if (!h)
  293.         return;
  294.  
  295.     size_t delta = RINGBUF_SUB(h->ridx, h->data);
  296.     size_t dest = RINGBUF_ADD((void *)h - (void *)buffer, delta);
  297.     //rb->logf("buf_ridx: %ld, buf_widx: %ld\n", (long)buf_ridx, (long)buf_widx);
  298.     //rb->logf("dest: %ld, delta: %ld\n", (long)dest, (long)delta);
  299.     h = move_handle(dest, h);
  300.     h->data = RINGBUF_ADD(h->data, delta);
  301.     h->ridx = h->data;
  302.     h->available -= delta;
  303.     //graph_view(100);
  304. }
  305.  
  306. /* Request a file be buffered
  307.     filename: name of the file t open
  308.     offset:   starting offset to buffer from the file
  309.     RETURNS:  <0 if the file cannot be opened, or one file already
  310.                 queued to be opened, otherwise the handle for the file in the buffer
  311. */
  312. int bufopen(char *file, size_t offset)
  313. {
  314.     /* add the file to the buffering queue. */
  315.     /* for now, we'll assume the queue is always empty, so the handle
  316.        gets added immediately */
  317.  
  318.     rb->logf("bufopen: %s (offset: %d)\n", file, offset);
  319.  
  320.     int fd = rb->open(file, O_RDONLY);
  321.     if (fd < 0)
  322.         return -1;
  323.  
  324.     if (offset)
  325.         rb->lseek(fd, offset, SEEK_SET);
  326.  
  327.     struct memory_handle *h = add_handle();
  328.     if (!h)
  329.         return -1;
  330.     rb->strncpy(h->path, file, MAX_PATH);
  331.     h->fd = fd;
  332.     h->filesize = rb->filesize(fd);
  333.     h->filerem = h->filesize - offset;
  334.     h->offset = offset;
  335.     h->ridx = buf_widx;
  336.     h->widx = buf_widx;
  337.     h->data = buf_widx;
  338.     h->available = 0;
  339.     rb->logf("h: %lx", (unsigned long)h);
  340.     rb->logf("h->id: %d", h->id);
  341.  
  342.     rb->logf("added handle : %d\n", h->id);
  343.     return h->id;
  344. }
  345.  
  346. /* Close the handle. Return 0 for success and < 0 for failure */
  347. int bufclose(int handle_id)
  348. {
  349.     rb->logf("bufclose(%d)\n", handle_id);
  350.     struct memory_handle *h = find_handle(handle_id);
  351.     if (!h)
  352.         return -1;
  353.  
  354.     rm_handle(h);
  355.     return 0;
  356. }
  357.  
  358. /* Set the reading index in a handle (relatively to the start of the handle data).
  359.    Return 0 for success and < 0 for failure */
  360. int bufseek(int handle_id, size_t offset)
  361. {
  362.     struct memory_handle *h = find_handle(handle_id);
  363.     if (!h)
  364.         return -1;
  365.  
  366.     if (offset > h->available)
  367.         return -2;
  368.  
  369.     h->ridx = RINGBUF_ADD(h->data, offset);
  370.     return 0;
  371. }
  372.  
  373. /* Advance the reading index in a handle (relatively to its current position).
  374.    Return 0 for success and < 0 for failure */
  375. int bufadvance(int handle_id, ssize_t offset)
  376. {
  377.     struct memory_handle *h = find_handle(handle_id);
  378.     if (!h)
  379.         return -1;
  380.  
  381.     if (offset >= 0)
  382.     {
  383.         if (offset > h->available - RINGBUF_SUB(h->ridx, h->data))
  384.             return -2;
  385.  
  386.         h->ridx = RINGBUF_ADD(h->ridx, offset);
  387.     }
  388.     else
  389.     {
  390.         if (-offset > RINGBUF_SUB(h->ridx, h->data))
  391.             return -2;
  392.  
  393.         h->ridx = RINGBUF_SUB(h->ridx, -offset);
  394.     }
  395.  
  396.     return 0;
  397. }
  398.  
  399. /* Copy data from the given handle to the dest buffer.
  400.    Return the number of bytes copied or -1 for failure. */
  401. int bufread(int handle_id, size_t size, char *dest)
  402. {
  403.     struct memory_handle *h = find_handle(handle_id);
  404.     size_t buffered_data;
  405.     if (!h)
  406.         return -1;
  407.     if (h->available == 0)
  408.         return 0;
  409.     buffered_data = MIN(size, h->available);
  410.  
  411.     if (h->ridx + buffered_data > buffer_len)
  412.     {
  413.         size_t read = buffer_len - h->ridx;
  414.         rb->memcpy(dest, &buffer[h->ridx], read);
  415.         rb->memcpy(dest+read, buffer, buffered_data - read);
  416.     }
  417.     else rb->memcpy(dest, &buffer[h->ridx], buffered_data);
  418.  
  419.     h->ridx = RINGBUF_ADD(h->ridx, buffered_data);
  420.     h->available -= buffered_data;
  421.     return buffered_data;
  422. }
  423.  
  424. /* Update the "data" pointer to make the handle's data available to the caller.
  425.    Return the length of the available linear data or -1 for failure. */
  426. long bufgetdata(int handle_id, size_t size, unsigned char **data)
  427. {
  428.     struct memory_handle *h = find_handle(handle_id);
  429.     if (!h)
  430.         return -1;
  431.  
  432.     long ret;
  433.  
  434.     if (h->ridx + size > buffer_len &&
  435.         h->available - RINGBUF_SUB(h->ridx, h->data) >= size)
  436.     {
  437.         /* use the guard buffer to provide what was requested. */
  438.         int copy_n = h->ridx + size - buffer_len;
  439.         rb->memcpy(guard_buffer, (unsigned char *)buffer, copy_n);
  440.         ret = size;
  441.     }
  442.     else
  443.     {
  444.         ret = MIN(h->available - RINGBUF_SUB(h->ridx, h->data),
  445.                   buffer_len - h->ridx);
  446.     }
  447.  
  448.     *data = (unsigned char *)(buffer + h->ridx);
  449.  
  450.     //rb->logf("bufgetdata(%d): h->ridx=%ld, ret=%ld\n", handle_id, (long)h->ridx, ret);
  451.     return ret;
  452. }
  453.  
  454. bool test_ll(void)
  455. {
  456.     struct memory_handle *m1, *m2, *m3, *m4;
  457.  
  458.     if (cur_handle != NULL || first_handle != NULL)
  459.         return false;
  460.  
  461.     m1 = add_handle();
  462.  
  463.     if (cur_handle != m1 || first_handle != m1 || m1->next != NULL)
  464.         return false;
  465.  
  466.     m2 = add_handle();
  467.  
  468.     if (cur_handle != m2 || first_handle != m1 || m1->next != m2 || m2->next != NULL)
  469.         return false;
  470.  
  471.     m3 = add_handle();
  472.  
  473.     if (cur_handle != m3 || first_handle != m1 || m2->next != m3 || m3->next != NULL)
  474.         return false;
  475.  
  476.     rm_handle(m2);
  477.  
  478.     if (cur_handle != m3 || first_handle != m1 || m1->next != m3)
  479.         return false;
  480.  
  481.     rm_handle(m3);
  482.  
  483.     if (cur_handle != m1 || first_handle != m1 || m1->next != NULL)
  484.         return false;
  485.  
  486.     m4 = add_handle();
  487.  
  488.     if (cur_handle != m4 || first_handle != m1 || m1->next != m4 || m4->next != NULL)
  489.         return false;
  490.  
  491.     rm_handle(m1);
  492.  
  493.     if (cur_handle != m4 || first_handle != m4)
  494.         return false;
  495.  
  496.     rm_handle(m4);
  497.  
  498.     if (cur_handle != NULL || first_handle != NULL)
  499.         return false;
  500.  
  501.     m1 = add_handle();
  502.     m2 = add_handle();
  503.     m3 = add_handle();
  504.     m4 = add_handle();
  505.  
  506.     if (cur_handle != m4 || first_handle != m1)
  507.         return false;
  508. /*
  509.     int m2id = m2->id;
  510.     m2 = move_handle(m2->data + 1024*1024, m2);
  511.  
  512.     if (cur_handle != m4 || first_handle != m1 || m1->next != m2 || m2->next != m3 ||
  513.         find_handle(m2id) != m2)
  514.         return false;
  515.  
  516.     int m1id = m1->id;
  517.     m1 = move_handle(m1->data + 1024*1024*3, m1);
  518.  
  519.     if (cur_handle != m4 || first_handle != m1 || m1->next != m2 ||
  520.         find_handle(m1id) != m1)
  521.         return false;*/
  522.  
  523.     rm_handle(m1);
  524.     rm_handle(m2);
  525.     rm_handle(m3);
  526.     rm_handle(m4);
  527.  
  528.     if (cur_handle != NULL || first_handle != NULL)
  529.         return false;
  530.  
  531.     return true;
  532. }
  533.  
  534. #if 0
  535. static void list_handles(void)
  536. {
  537.     struct memory_handle *m = first_handle;
  538.     while (m) {
  539.         rb->logf("%02d - %d\n", m->id, (void *)m-(void *)buffer);
  540.         m = m->next;
  541.     }
  542. }
  543. #endif
  544.  
  545. /* display a nice graphical view of the ringbuffer. */
  546. static void graph_view(int width)
  547. {
  548.     int i, r_pos, w_pos;
  549.     r_pos = buf_ridx * width / buffer_len;
  550.     w_pos = buf_widx * width / buffer_len;
  551.  
  552.     rb->logf("|");
  553.     for (i=0; i <= width; i++)
  554.     {
  555.         if (i != r_pos && i != w_pos)
  556.         {
  557.             if (buf_ridx <= buf_widx)
  558.             {
  559.                 if (i > r_pos && i < w_pos) {
  560.                     rb->logf(">");
  561.                 } else {
  562.                     rb->logf("-");
  563.                 }
  564.             }
  565.             else
  566.             {
  567.                 if (i > r_pos || i < w_pos) {
  568.                     rb->logf(">");
  569.                 } else {
  570.                     rb->logf("-");
  571.                 }
  572.             }
  573.         }
  574.         else
  575.         {
  576.             if (i == r_pos && i == w_pos)
  577.             {
  578.                 if (buf_ridx <= buf_widx) {
  579.                     rb->logf("RW");
  580.                 } else {
  581.                     rb->logf("WR");
  582.                 }
  583.             } else if (i == r_pos) {
  584.                 rb->logf("R");
  585.             } else if (i == w_pos) {
  586.                 rb->logf("W");
  587.             }
  588.         }
  589.     }
  590.     rb->logf("|");
  591.     rb->logf("\n");
  592. }
  593.  
  594. bool buffer_init(void)
  595. {
  596.     buffer = rb->plugin_get_audio_buffer(&buffer_len);
  597.     if (!buffer)
  598.     {
  599.         rb->logf("couldn't allocate buffer\n");
  600.         return false;
  601.     }
  602.     buffer_len -= GUARD_SIZE;
  603.     guard_buffer = buffer + buffer_len;
  604.  
  605.     buf_widx = 0;
  606.     buf_ridx = 0;
  607.  
  608.     first_handle = NULL;
  609.     num_handles = 0;
  610.  
  611.     conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
  612.  
  613.     return true;
  614. }
  615.  
  616. /* returns true if the file still has some on disk unread */
  617. bool handle_has_data(int handle)
  618. {
  619.     struct memory_handle *m = find_handle(handle);
  620.     if (m)
  621.     {
  622.         return m->filerem != 0;
  623.     }
  624.     return false;
  625. }
  626.  
  627. bool need_rebuffer(void)
  628. {
  629.     size_t free, wasted;
  630.     wasted = first_handle? RINGBUF_SUB(first_handle->ridx, first_handle->data) : 0;
  631.     while (wasted > buffer_len / 2)
  632.     {
  633.         free_buffer(first_handle->id);
  634.         wasted = first_handle? RINGBUF_SUB(first_handle->ridx, first_handle->data) : 0;
  635.     }
  636.     free = buffer_len - BUF_USED;
  637.     return ((free >= buffer_len/4));
  638. }
  639.  
  640. bool disk_is_spinning(void)
  641. {
  642.     return true;
  643. }
  644.  
  645. #define MAX_HANDLES 64
  646.  
  647. /* this is the plugin entry point */
  648. enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
  649. {
  650.     (void)parameter;
  651.     rb = api;
  652.  
  653.     int argc = 6;
  654.     char *argv[] = { NULL,
  655.             "/070623 - David Vendetta.mp3",
  656.             "/africanism all stars feat the hard boys - hard (bob sinclair remix).mp3",
  657.             "/alan_braxe__kris_menace_-_lumberjack.mp3",
  658.             "/Ame - Rej (A Hundred Birds Remix).mp3",
  659.             "/Antena - Camino del Sol (Joakim Remix).mp3" };
  660.  
  661.     int next_file = 1;
  662.     int last_handle = -1;
  663.     int handle_order[MAX_HANDLES];
  664.     int reading_handle = 0;
  665.     bool done_buffering = false, done_playing = false;
  666.     //char read_buffer[GUARD_SIZE];
  667.     unsigned char *data;
  668.     int fd = -1; /* used to write the files out as they are read */
  669.     int current_handle = -1;
  670.     struct memory_handle *m = NULL;
  671.     buffer_init();
  672.  
  673.     if (!test_ll())
  674.     {
  675.         rb->logf("linked list test failed\n");
  676.         rb->splash(HZ, "linked list test failed");
  677.         return PLUGIN_ERROR;
  678.     }
  679.  
  680.     buffer_init();
  681.    
  682.     rb->logf("test\n");
  683.  
  684.     while (!done_buffering || !done_playing)
  685.     {
  686.         rb->logf("buffer usage: %d handles_used: %d\n", BUF_USED, num_handles);
  687.         //graph_view(100);
  688.  
  689.         /* "Buffering thread" section */
  690.         if (!done_buffering && need_rebuffer() && disk_is_spinning())
  691.         {
  692.             m = find_handle(current_handle);
  693.             if ( !m || ((m->filerem == 0) && (m->next == NULL)))
  694.             {
  695.                 int h = bufopen(argv[next_file], 0);
  696.                 m = find_handle(h);
  697.                 if (h >= 0)
  698.                 {
  699.                     next_file++;
  700.                     //rb->logf("new handle %d\n",h);
  701.                     last_handle++;
  702.                     handle_order[last_handle] = h;
  703.                     buffer_handle(m->id);
  704.                 }
  705.                 else
  706.                 {
  707.                     rb->logf("error\n");
  708.                 }
  709.                 current_handle = h;
  710.             }
  711.             else
  712.             {
  713.                 if (m->filerem == 0)
  714.                 {
  715.                     m = m->next;
  716.                     current_handle = m?m->id:-1;
  717.                 }
  718.                 if (m)
  719.                 {
  720.                     rb->logf("buffering handle %d\n",m->id);
  721.                     buffer_handle(m->id);
  722.                 }
  723.             }
  724.  
  725.             if (next_file == argc && m->filerem == 0)
  726.                 done_buffering = true;
  727.         }
  728.         /* "Playback thread" section */
  729.         else
  730.         {
  731.             rb->logf("reading handle: %d\n", handle_order[reading_handle]);
  732.             long read;
  733.             long total = 0;
  734.             char file[MAX_PATH];
  735.             if (reading_handle >= last_handle
  736.                 && !handle_has_data(handle_order[reading_handle]))
  737.                 done_playing = true;
  738.  
  739.             if (fd < 0)
  740.             {
  741.                 rb->snprintf(file, MAX_PATH, "/file%d.mp3", reading_handle);
  742.                 fd = rb->open(file, O_CREAT|O_TRUNC|O_WRONLY);
  743.                 if (fd < 0)
  744.                 {
  745.                     rb->logf("ERROROROROR\n");
  746.                     rb->splash(HZ, "couldn't create file");
  747.                     return PLUGIN_ERROR;
  748.                 }
  749.             }
  750.             do
  751.             {
  752.                 //read = bufread(handle_order[reading_handle], GUARD_SIZE,read_buffer);
  753.                 //write(fd, read_buffer, read);
  754.                 read = bufgetdata(handle_order[reading_handle], GUARD_SIZE, &data);
  755.                 read = MIN(read, GUARD_SIZE);
  756.                 rb->write(fd, data, read);
  757.                 total += read;
  758.                 bufadvance(handle_order[reading_handle], read);
  759.             }
  760.             while (read > 0);
  761.  
  762.             rb->logf("read %ld bytes from handle %d\n", total, handle_order[reading_handle]);
  763.  
  764.             /* close the fd/handle if there is no more data or an error */
  765.             if (read < 0 || handle_has_data(handle_order[reading_handle]) == false)
  766.             {
  767.                 rb->logf("finished reading %d\n",handle_order[reading_handle]);
  768.                 bufclose(handle_order[reading_handle]);
  769.                 rb->close(fd);
  770.                 reading_handle++;
  771.                 fd = -1;
  772.             }
  773.             else
  774.             {
  775.                 rb->logf("there is data left to buffer for %d\n", handle_order[reading_handle]);
  776.             }
  777.         }
  778.     }
  779.  
  780.     rb->logf("buffer usage: %d handles_used: %d\n", BUF_USED,num_handles);
  781.     //graph_view(100);
  782.  
  783.     return 0;
  784.  
  785.     return PLUGIN_OK;
  786. }

Update the Post

Either update this post and resubmit it with changes, or make a new post.

You may also comment on this post.

update paste below
details of the post (optional)

Note: Only the paste content is required, though the following information can be useful to others.

Save name / title?

(space separated, optional)



Please note that information posted here will expire by default in one month. If you do not want it to expire, please set the expiry time above. If it is set to expire, web search engines will not be allowed to index it prior to it expiring. Items that are not marked to expire will be indexable by search engines. Be careful with your passwords. All illegal activities will be reported and any information will be handed over to the authorities, so be good.

comments powered by Disqus