| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 | 
							- /* 
 
-  *  Squeezelite - lightweight headless squeezebox emulator
 
-  *
 
-  *  (c) Adrian Smith 2012-2015, triode1@btinternet.com
 
-  *      Ralph Irving 2015-2017, ralph_irving@hotmail.com
 
-  *
 
-  * 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 3 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, see <http://www.gnu.org/licenses/>.
 
-  *
 
-  */
 
- // fifo bufffers 
 
- #ifndef _GNU_SOURCE
 
- #define _GNU_SOURCE
 
- #endif
 
- #include "squeezelite.h"
 
- // _* called with muxtex locked
 
- inline unsigned _buf_used(struct buffer *buf) {
 
- 	return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->size - (buf->readp - buf->writep);
 
- }
 
- unsigned _buf_space(struct buffer *buf) {
 
- 	return buf->size - _buf_used(buf) - 1; // reduce by one as full same as empty otherwise
 
- }
 
- unsigned _buf_cont_read(struct buffer *buf) {
 
- 	return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->wrap - buf->readp;
 
- }
 
- unsigned _buf_cont_write(struct buffer *buf) {
 
- 	return buf->writep >= buf->readp ? buf->wrap - buf->writep : buf->readp - buf->writep;
 
- }
 
- void _buf_inc_readp(struct buffer *buf, unsigned by) {
 
- 	buf->readp += by;
 
- 	if (buf->readp >= buf->wrap) {
 
- 		buf->readp -= buf->size;
 
- 	}
 
- }
 
- void _buf_inc_writep(struct buffer *buf, unsigned by) {
 
- 	buf->writep += by;
 
- 	if (buf->writep >= buf->wrap) {
 
- 		buf->writep -= buf->size;
 
- 	}
 
- }
 
- void buf_flush(struct buffer *buf) {
 
- 	mutex_lock(buf->mutex);
 
- 	buf->readp  = buf->buf;
 
- 	buf->writep = buf->buf;
 
- 	mutex_unlock(buf->mutex);
 
- }
 
- void _buf_flush(struct buffer *buf) {
 
- 	buf->readp  = buf->buf;
 
- 	buf->writep = buf->buf;
 
- }
 
- // adjust buffer to multiple of mod bytes so reading in multiple always wraps on frame boundary
 
- void buf_adjust(struct buffer *buf, size_t mod) {
 
- 	mutex_lock(buf->mutex);
 
- 	buf->base_size = ((size_t)(buf->size / mod)) * mod;
 
- 	buf->readp  = buf->writep = buf->buf;
 
- 	buf->wrap   = buf->buf + buf->base_size;
 
- 	buf->size   = buf->base_size;
 
- 	mutex_unlock(buf->mutex);
 
- }
 
- // called with mutex locked to resize, does not retain contents, reverts to original size if fails
 
- void _buf_resize(struct buffer *buf, size_t size) {
 
- 	if (size == buf->size) return;
 
- 	free(buf->buf);
 
- 	buf->buf = malloc(size);
 
- 	if (!buf->buf) {
 
- 		size    = buf->size;
 
- 		buf->buf = malloc(size);
 
- 		if (!buf->buf) size = 0;
 
- 	}
 
- 	buf->writep = buf->readp  = buf->buf;
 
- 	buf->wrap   = buf->buf + size;
 
- 	buf->true_size = buf->base_size = buf->size = size;
 
- }
 
- size_t _buf_limit(struct buffer *buf, size_t limit) {
 
- 	if (limit) {
 
- 		buf->size = limit;
 
- 		buf->readp = buf->writep = buf->buf;
 
- 	} else {
 
- 		buf->size = buf->base_size;
 
- 	}
 
- 	buf->wrap = buf->buf + buf->size;
 
- 	return buf->base_size - buf->size;
 
- }
 
- void _buf_unwrap(struct buffer *buf, size_t cont) {
 
- 	ssize_t len, by = cont - (buf->wrap - buf->readp);
 
- 	size_t size;
 
- 	u8_t *scratch;
 
- 	// do nothing if we have enough space
 
- 	if (by <= 0 || cont >= buf->size) return;
 
- 	// buffer already unwrapped, just move it up
 
- 	if (buf->writep >= buf->readp) {
 
- 		memmove(buf->readp - by, buf->readp, buf->writep - buf->readp);
 
- 		buf->readp -= by;
 
- 		buf->writep -= by;
 
- 		return;
 
- 	 }
 
- 	// how much is overlapping
 
- 	size = by - (buf->readp - buf->writep);
 
- 	len = buf->writep - buf->buf;
 
- 	// buffer is wrapped and enough free space to move data up directly
 
- 	if (size <= 0) {
 
- 		memmove(buf->readp - by, buf->readp, buf->wrap - buf->readp);
 
- 		buf->readp -= by;
 
- 		memcpy(buf->wrap - by, buf->buf, min(len, by));
 
- 		if (len > by) {
 
- 			memmove(buf->buf, buf->buf + by, len - by);
 
- 			buf->writep -= by;
 
- 		} else {
 
- 			buf->writep += buf->size - by;
 
- 		}
 
- 		return;
 
- 	}
 
- 	scratch = malloc(size);
 
- 	// buffer is wrapped but not enough free room => use scratch zone
 
- 	if (scratch) {
 
- 		memcpy(scratch, buf->writep - size, size);
 
- 		memmove(buf->readp - by, buf->readp, buf->wrap - buf->readp);
 
- 		buf->readp -= by;
 
- 		memcpy(buf->wrap - by, buf->buf, by);
 
- 		memmove(buf->buf, buf->buf + by, len - by - size);
 
- 		buf->writep -= by;
 
- 		memcpy(buf->writep - size, scratch, size);
 
- 		free(scratch);
 
- 	} else {
 
- 		_buf_unwrap(buf, cont / 2);
 
-         _buf_unwrap(buf, cont - cont / 2);
 
- 	}
 
- }
 
- void buf_init(struct buffer *buf, size_t size) {
 
- 	buf->buf    = malloc(size);
 
- 	buf->readp  = buf->buf;
 
- 	buf->writep = buf->buf;
 
- 	buf->wrap   = buf->buf + size;
 
- 	buf->true_size = buf->base_size = buf->size = size;
 
- 	mutex_create_p(buf->mutex);
 
- }
 
- void buf_destroy(struct buffer *buf) {
 
- 	if (buf->buf) {
 
- 		free(buf->buf);
 
- 		buf->buf = NULL;
 
- 		buf->size = buf->base_size = buf->true_size = 0;
 
- 		mutex_destroy(buf->mutex);
 
- 	}
 
- }
 
 
  |