diff options
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/metadataChunk.c | 0 | ||||
-rw-r--r-- | src/metadataChunk.h | 0 | ||||
-rw-r--r-- | src/metadata_pipe.c | 151 | ||||
-rw-r--r-- | src/ringbuf.c | 311 | ||||
-rw-r--r-- | src/ringbuf.h | 227 |
6 files changed, 0 insertions, 691 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8debfb6a7..6f11caaab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,7 +59,6 @@ mpd_headers = \ playlist.h \ playlist_save.h \ replayGain.h \ - ringbuf.h \ signal_check.h \ sig_handlers.h \ song.h \ @@ -138,7 +137,6 @@ mpd_SOURCES = \ playlist.c \ playlist_save.c \ replayGain.c \ - ringbuf.c \ sig_handlers.c \ signal_check.c \ song.c \ diff --git a/src/metadataChunk.c b/src/metadataChunk.c deleted file mode 100644 index e69de29bb..000000000 --- a/src/metadataChunk.c +++ /dev/null diff --git a/src/metadataChunk.h b/src/metadataChunk.h deleted file mode 100644 index e69de29bb..000000000 --- a/src/metadataChunk.h +++ /dev/null diff --git a/src/metadata_pipe.c b/src/metadata_pipe.c deleted file mode 100644 index 83c36ce1b..000000000 --- a/src/metadata_pipe.c +++ /dev/null @@ -1,151 +0,0 @@ -/* the Music Player Daemon (MPD) - * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com) - * This project's homepage is: http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "metadata_pipe.h" -#include "ringbuf.h" -#include "decode.h" -#include "os_compat.h" -#include "log.h" -#include "outputBuffer.h" -#include "gcc.h" - -static struct ringbuf *mp; - -/* Each one of these is a packet inside the metadata pipe */ -struct tag_container { - float metadata_time; - uint8_t seq; /* ob.seq_decoder at time of metadata_pipe_send() */ - struct mpd_tag *tag; /* our payload */ -}; - -/* - * We have two readers even though ringbuf was designed for one (locklessly), - * so we will use a lock to allow readers to safely read. Writing is only - * done from one thread, so it will never block or clobber. - */ -static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER; -static struct mpd_tag *current_tag; /* requires read_lock for both r/w access */ - -static void metadata_pipe_finish(void) -{ - ringbuf_free(mp); - if (current_tag) - tag_free(current_tag); -} - -void init_metadata_pipe(void) -{ - mp = ringbuf_create(sizeof(struct tag_container) * 16); - atexit(metadata_pipe_finish); -} - -void metadata_pipe_send(struct mpd_tag *tag, float metadata_time) -{ - struct tag_container tc; - size_t written; - - assert(pthread_equal(pthread_self(), dc.thread)); - - if (mpd_unlikely(ringbuf_write_space(mp) - < sizeof(struct tag_container))) { - DEBUG("metadata_pipe: insufficient buffer space, dropping\n"); - tag_free(tag); - return; - } - - tc.tag = tag; - tc.metadata_time = metadata_time; - tc.seq = ob_get_decoder_sequence(); - written = ringbuf_write(mp, &tc, sizeof(struct tag_container)); - assert(written == sizeof(struct tag_container)); -} - -struct mpd_tag * metadata_pipe_recv(void) -{ - struct tag_container tc; - size_t r; - static const size_t uint8_t_max = 255; /* XXX CLEANUP */ - uint8_t expect_seq = ob_get_player_sequence(); - unsigned long current_time = ob_get_elapsed_time(); - struct mpd_tag *tag = NULL; - - if (pthread_mutex_trylock(&read_lock) == EBUSY) - return NULL; -retry: - if (!(r = ringbuf_peek(mp, &tc, sizeof(struct tag_container)))) - goto out; - - assert(r == sizeof(struct tag_container)); - assert(tc.tag); - if (expect_seq == tc.seq) { - if (current_time < tc.metadata_time) - goto out; /* not ready for tag yet */ - if (tag_equal(tc.tag, current_tag)) { - tag_free(tc.tag); - ringbuf_read_advance(mp, sizeof(struct tag_container)); - goto out; /* nothing changed, don't bother */ - } - tag = tag_dup(tc.tag); - if (current_tag) - tag_free(current_tag); - current_tag = tc.tag; - ringbuf_read_advance(mp, sizeof(struct tag_container)); - } else if (expect_seq > tc.seq || - (!expect_seq && tc.seq == uint8_t_max)) { - DEBUG("metadata_pipe: reader is ahead of writer\n"); - tag_free(tc.tag); - ringbuf_read_advance(mp, sizeof(struct tag_container)); - goto retry; /* read and skip packets */ - } /* else not ready for tag yet */ -out: - pthread_mutex_unlock(&read_lock); - return tag; -} - -struct mpd_tag *metadata_pipe_current(void) -{ - struct mpd_tag *tag; - - assert(! pthread_equal(pthread_self(), dc.thread)); - if (pthread_mutex_trylock(&read_lock) == EBUSY) - return NULL; - tag = current_tag ? tag_dup(current_tag) : NULL; - pthread_mutex_unlock(&read_lock); - - return tag; -} - -void metadata_pipe_clear(void) -{ - struct tag_container tc; - size_t r; - - pthread_mutex_lock(&read_lock); - - while ((r = ringbuf_read(mp, &tc, sizeof(struct tag_container)))) { - assert(r == sizeof(struct tag_container)); - tag_free(tc.tag); - } - - if (current_tag) { - tag_free(current_tag); - current_tag = NULL; - } - - pthread_mutex_unlock(&read_lock); -} diff --git a/src/ringbuf.c b/src/ringbuf.c deleted file mode 100644 index e99f26fc6..000000000 --- a/src/ringbuf.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * This file is originally from JACK Audio Connection Kit - * - * Copyright (C) 2000 Paul Davis - * Copyright (C) 2003 Rohan Drape - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code. - * This is safe for the case of one read thread and one write thread. - */ - -#include "ringbuf.h" -#include "utils.h" - -#include <string.h> - -#define advance_ptr(ptr,cnt,mask) ptr = (ptr + cnt) & mask - -/* - * Create a new ringbuffer to hold at least `sz' bytes of data. The - * actual buffer size is rounded up to the next power of two. - */ -struct ringbuf *ringbuf_create(size_t sz) -{ - struct ringbuf *rb = xmalloc(sizeof(struct ringbuf)); - size_t power_of_two; - - for (power_of_two = 1; (size_t)(1 << power_of_two) < sz; power_of_two++) - /* next power_of_two... */; - - rb->size = 1 << power_of_two; - rb->size_mask = rb->size; - rb->size_mask -= 1; - rb->buf = xmalloc(rb->size); - ringbuf_reset(rb); - - return rb; -} - -/* Free all data associated with the ringbuffer `rb'. */ -void ringbuf_free(struct ringbuf * rb) -{ - free(rb->buf); - free(rb); -} - -/* Reset the read and write pointers to zero. This is not thread safe. */ -void ringbuf_reset(struct ringbuf * rb) -{ - rb->read_ptr = 0; - rb->write_ptr = 0; -} - -/* Reset the read and write pointers, thread-safe iff called only by writer */ -void ringbuf_writer_reset(struct ringbuf * rb) -{ - rb->write_ptr = rb->read_ptr; -} - -/* Reset the read and write pointers, thread-safe iff called only by reader */ -void ringbuf_reader_reset(struct ringbuf * rb) -{ - rb->read_ptr = rb->write_ptr; -} - -/* - * Return the number of bytes available for reading. This is the - * number of bytes in front of the read pointer and behind the write - * pointer. - */ -size_t ringbuf_read_space(const struct ringbuf * rb) -{ - size_t w = rb->write_ptr; - size_t r = rb->read_ptr; - - if (w > r) - return w - r; - else - return (w - r + rb->size) & rb->size_mask; -} - -/* - * Return the number of bytes available for writing. This is the - * number of bytes in front of the write pointer and behind the read - * pointer. - */ -size_t ringbuf_write_space(const struct ringbuf * rb) -{ - size_t w = rb->write_ptr; - size_t r = rb->read_ptr; - - if (w > r) - return ((r - w + rb->size) & rb->size_mask) - 1; - else if (w < r) - return (r - w) - 1; - else - return rb->size - 1; -} - -/* - * The copying data reader. Copy at most `cnt' bytes from `rb' to - * `dest'. Returns the actual number of bytes copied. - */ -size_t ringbuf_read(struct ringbuf * rb, void *dest, size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - - if ((free_cnt = ringbuf_read_space(rb)) == 0) - return 0; - - to_read = cnt > free_cnt ? free_cnt : cnt; - cnt2 = rb->read_ptr + to_read; - - if (cnt2 > rb->size) { - n1 = rb->size - rb->read_ptr; - n2 = cnt2 & rb->size_mask; - } else { - n1 = to_read; - n2 = 0; - } - - memcpy(dest, rb->buf + rb->read_ptr, n1); - ringbuf_read_advance(rb, n1); - - if (n2) { - memcpy((char*)dest + n1, rb->buf + rb->read_ptr, n2); - ringbuf_read_advance(rb, n2); - } - - return to_read; -} - -/* - * The copying data reader w/o read pointer advance. Copy at most - * `cnt' bytes from `rb' to `dest'. Returns the actual number of bytes - * copied. - */ -size_t ringbuf_peek(struct ringbuf * rb, void *dest, size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_read; - size_t n1, n2; - size_t tmp_read_ptr = rb->read_ptr; - - if ((free_cnt = ringbuf_read_space(rb)) == 0) - return 0; - - to_read = cnt > free_cnt ? free_cnt : cnt; - cnt2 = tmp_read_ptr + to_read; - - if (cnt2 > rb->size) { - n1 = rb->size - tmp_read_ptr; - n2 = cnt2 & rb->size_mask; - } else { - n1 = to_read; - n2 = 0; - } - - memcpy(dest, rb->buf + tmp_read_ptr, n1); - advance_ptr(tmp_read_ptr, n1, rb->size_mask); - - if (n2) { - memcpy((char*)dest + n1, rb->buf + tmp_read_ptr, n2); - advance_ptr(tmp_read_ptr, n2, rb->size_mask); - } - - return to_read; -} - -/* - * The copying data writer. Copy at most `cnt' bytes to `rb' from - * `src'. Returns the actual number of bytes copied. - */ -size_t ringbuf_write(struct ringbuf * rb, const void *src, size_t cnt) -{ - size_t free_cnt; - size_t cnt2; - size_t to_write; - size_t n1, n2; - - if ((free_cnt = ringbuf_write_space(rb)) == 0) - return 0; - - to_write = cnt > free_cnt ? free_cnt : cnt; - cnt2 = rb->write_ptr + to_write; - - if (cnt2 > rb->size) { - n1 = rb->size - rb->write_ptr; - n2 = cnt2 & rb->size_mask; - } else { - n1 = to_write; - n2 = 0; - } - - memcpy(rb->buf + rb->write_ptr, src, n1); - ringbuf_write_advance(rb, n1); - - if (n2) { - memcpy(rb->buf + rb->write_ptr, (const char*)src + n1, n2); - ringbuf_write_advance(rb, n2); - } - - return to_write; -} - -/* Advance the read pointer `cnt' places. */ -void ringbuf_read_advance(struct ringbuf * rb, size_t cnt) -{ - advance_ptr(rb->read_ptr, cnt, rb->size_mask); -} - -/* Advance the write pointer `cnt' places. */ -void ringbuf_write_advance(struct ringbuf * rb, size_t cnt) -{ - advance_ptr(rb->write_ptr, cnt, rb->size_mask); -} - -/* - * The non-copying data reader. `vec' is an array of two places. Set - * the values at `vec' to hold the current readable data at `rb'. If - * the readable data is in one segment the second segment has zero - * length. - */ -size_t ringbuf_get_read_vector(const struct ringbuf * rb, struct iovec * vec) -{ - size_t free_cnt; - size_t cnt2; - size_t w = rb->write_ptr; - size_t r = rb->read_ptr; - - if (w > r) - free_cnt = w - r; - else - free_cnt = (w - r + rb->size) & rb->size_mask; - - cnt2 = r + free_cnt; - - if (cnt2 > rb->size) { - /* - * Two part vector: the rest of the buffer after the current - * write ptr, plus some from the start of the buffer. - */ - vec[0].iov_base = rb->buf + r; - vec[0].iov_len = rb->size - r; - vec[1].iov_base = rb->buf; - vec[1].iov_len = cnt2 & rb->size_mask; - } else { - /* Single part vector: just the rest of the buffer */ - vec[0].iov_base = rb->buf + r; - vec[0].iov_len = free_cnt; - vec[1].iov_len = 0; - } - return vec[0].iov_len + vec[1].iov_len; -} - -/* - * The non-copying data writer. `vec' is an array of two places. Set - * the values at `vec' to hold the current writeable data at `rb'. If - * the writeable data is in one segment the second segment has zero - * length. - */ -size_t ringbuf_get_write_vector(const struct ringbuf * rb, struct iovec * vec) -{ - size_t free_cnt; - size_t cnt2; - size_t w = rb->write_ptr; - size_t r = rb->read_ptr; - - if (w > r) - free_cnt = ((r - w + rb->size) & rb->size_mask) - 1; - else if (w < r) - free_cnt = (r - w) - 1; - else - free_cnt = rb->size - 1; - - cnt2 = w + free_cnt; - - if (cnt2 > rb->size) { - /* - * Two part vector: the rest of the buffer after the current - * write ptr, plus some from the start of the buffer. - */ - vec[0].iov_base = rb->buf + w; - vec[0].iov_len = rb->size - w; - vec[1].iov_base = rb->buf; - vec[1].iov_len = cnt2 & rb->size_mask; - } else { - vec[0].iov_base = rb->buf + w; - vec[0].iov_len = free_cnt; - vec[1].iov_len = 0; - } - return vec[0].iov_len + vec[1].iov_len; -} - diff --git a/src/ringbuf.h b/src/ringbuf.h deleted file mode 100644 index f45ab2da9..000000000 --- a/src/ringbuf.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * This file is originally from JACK Audio Connection Kit - * - * Copyright (C) 2000 Paul Davis - * Copyright (C) 2003 Rohan Drape - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef MPD_RINGBUF_H -#define MPD_RINGBUF_H - -#include <stddef.h> -#include <sys/uio.h> - -/** @file ringbuf.h - * - * A set of library functions to make lock-free ringbuffers available - * to JACK clients. The `capture_client.c' (in the example_clients - * directory) is a fully functioning user of this API. - * - * The key attribute of a ringbuffer is that it can be safely accessed - * by two threads simultaneously -- one reading from the buffer and - * the other writing to it -- without using any synchronization or - * mutual exclusion primitives. For this to work correctly, there can - * only be a single reader and a single writer thread. Their - * identities cannot be interchanged. - */ - -struct ringbuf { - unsigned char *buf; - size_t write_ptr; - size_t read_ptr; - size_t size; - size_t size_mask; -}; - -/** - * Allocates a ringbuffer data structure of a specified size. The - * caller must arrange for a call to ringbuf_free() to release - * the memory associated with the ringbuffer. - * - * @param sz the ringbuffer size in bytes. - * - * @return a pointer to a new struct ringbuf, if successful; NULL - * otherwise. - */ -struct ringbuf *ringbuf_create(size_t sz); - -/** - * Frees the ringbuffer data structure allocated by an earlier call to - * ringbuf_create(). - * - * @param rb a pointer to the ringbuffer structure. - */ -void ringbuf_free(struct ringbuf * rb); - -/** - * Fill a data structure with a description of the current readable - * data held in the ringbuffer. This description is returned in a two - * element array of struct iovec. Two elements are needed - * because the data to be read may be split across the end of the - * ringbuffer. - * - * The first element will always contain a valid @a len field, which - * may be zero or greater. If the @a len field is non-zero, then data - * can be read in a contiguous fashion using the address given in the - * corresponding @a buf field. - * - * If the second element has a non-zero @a len field, then a second - * contiguous stretch of data can be read from the address given in - * its corresponding @a buf field. - * - * @param rb a pointer to the ringbuffer structure. - * @param vec a pointer to a 2 element array of struct iovec. - * - * @return total number of bytes readable into both vec elements - */ -size_t ringbuf_get_read_vector(const struct ringbuf * rb, struct iovec * vec); - -/** - * Fill a data structure with a description of the current writable - * space in the ringbuffer. The description is returned in a two - * element array of struct iovec. Two elements are needed - * because the space available for writing may be split across the end - * of the ringbuffer. - * - * The first element will always contain a valid @a len field, which - * may be zero or greater. If the @a len field is non-zero, then data - * can be written in a contiguous fashion using the address given in - * the corresponding @a buf field. - * - * If the second element has a non-zero @a len field, then a second - * contiguous stretch of data can be written to the address given in - * the corresponding @a buf field. - * - * @param rb a pointer to the ringbuffer structure. - * @param vec a pointer to a 2 element array of struct iovec. - * - * @return total number of bytes writable in both vec elements - */ -size_t ringbuf_get_write_vector(const struct ringbuf * rb, struct iovec * vec); - -/** - * Read data from the ringbuffer. - * - * @param rb a pointer to the ringbuffer structure. - * @param dest a pointer to a buffer where data read from the - * ringbuffer will go. - * @param cnt the number of bytes to read. - * - * @return the number of bytes read, which may range from 0 to cnt. - */ -size_t ringbuf_read(struct ringbuf * rb, void *dest, size_t cnt); - -/** - * Read data from the ringbuffer. Opposed to ringbuf_read() - * this function does not move the read pointer. Thus it's - * a convenient way to inspect data in the ringbuffer in a - * continous fashion. The price is that the data is copied - * into a user provided buffer. For "raw" non-copy inspection - * of the data in the ringbuffer use ringbuf_get_read_vector(). - * - * @param rb a pointer to the ringbuffer structure. - * @param dest a pointer to a buffer where data read from the - * ringbuffer will go. - * @param cnt the number of bytes to read. - * - * @return the number of bytes read, which may range from 0 to cnt. - */ -size_t ringbuf_peek(struct ringbuf * rb, void *dest, size_t cnt); - -/** - * Advance the read pointer. - * - * After data have been read from the ringbuffer using the pointers - * returned by ringbuf_get_read_vector(), use this function to - * advance the buffer pointers, making that space available for future - * write operations. - * - * @param rb a pointer to the ringbuffer structure. - * @param cnt the number of bytes read. - */ -void ringbuf_read_advance(struct ringbuf * rb, size_t cnt); - -/** - * Return the number of bytes available for reading. - * - * @param rb a pointer to the ringbuffer structure. - * - * @return the number of bytes available to read. - */ -size_t ringbuf_read_space(const struct ringbuf * rb); - -/** - * Reset the read and write pointers, making an empty buffer. - * - * This is not thread safe. - * - * @param rb a pointer to the ringbuffer structure. - */ -void ringbuf_reset(struct ringbuf * rb); - -/** - * Reset the write pointer to the read pointer, making an empty buffer. - * - * This should only be called by the writer - * - * @param rb a pointer to the ringbuffer structure. - */ -void ringbuf_writer_reset(struct ringbuf * rb); - -/** - * Reset the read pointer to the write pointer, making an empty buffer. - * - * This should only be called by the reader - * - * @param rb a pointer to the ringbuffer structure. - */ -void ringbuf_reader_reset(struct ringbuf * rb); - -/** - * Write data into the ringbuffer. - * - * @param rb a pointer to the ringbuffer structure. - * @param src a pointer to the data to be written to the ringbuffer. - * @param cnt the number of bytes to write. - * - * @return the number of bytes write, which may range from 0 to cnt - */ -size_t ringbuf_write(struct ringbuf * rb, const void *src, size_t cnt); - -/** - * Advance the write pointer. - * - * After data have been written the ringbuffer using the pointers - * returned by ringbuf_get_write_vector(), use this function - * to advance the buffer pointer, making the data available for future - * read operations. - * - * @param rb a pointer to the ringbuffer structure. - * @param cnt the number of bytes written. - */ -void ringbuf_write_advance(struct ringbuf * rb, size_t cnt); - -/** - * Return the number of bytes available for writing. - * - * @param rb a pointer to the ringbuffer structure. - * - * @return the amount of free space (in bytes) available for writing. - */ -size_t ringbuf_write_space(const struct ringbuf * rb); - -#endif /* RINGBUF_H */ |