1 /*
2  *  Squeezelite - lightweight headless squeezebox emulator
3  *
4  *  (c) Adrian Smith 2012-2015, triode1@btinternet.com
5  *      Ralph Irving 2015-2017, ralph_irving@hotmail.com
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 // fifo bufffers
23 
24 #define _GNU_SOURCE
25 
26 #include "squeezelite.h"
27 
28 // _* called with muxtex locked
29 
_buf_used(struct buffer * buf)30 inline unsigned _buf_used(struct buffer *buf) {
31 	return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->size - (buf->readp - buf->writep);
32 }
33 
_buf_space(struct buffer * buf)34 unsigned _buf_space(struct buffer *buf) {
35 	return buf->size - _buf_used(buf) - 1; // reduce by one as full same as empty otherwise
36 }
37 
_buf_cont_read(struct buffer * buf)38 unsigned _buf_cont_read(struct buffer *buf) {
39 	return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->wrap - buf->readp;
40 }
41 
_buf_cont_write(struct buffer * buf)42 unsigned _buf_cont_write(struct buffer *buf) {
43 	return buf->writep >= buf->readp ? buf->wrap - buf->writep : buf->readp - buf->writep;
44 }
45 
_buf_inc_readp(struct buffer * buf,unsigned by)46 void _buf_inc_readp(struct buffer *buf, unsigned by) {
47 	buf->readp += by;
48 	if (buf->readp >= buf->wrap) {
49 		buf->readp -= buf->size;
50 	}
51 }
52 
_buf_inc_writep(struct buffer * buf,unsigned by)53 void _buf_inc_writep(struct buffer *buf, unsigned by) {
54 	buf->writep += by;
55 	if (buf->writep >= buf->wrap) {
56 		buf->writep -= buf->size;
57 	}
58 }
59 
buf_flush(struct buffer * buf)60 void buf_flush(struct buffer *buf) {
61 	mutex_lock(buf->mutex);
62 	buf->readp  = buf->buf;
63 	buf->writep = buf->buf;
64 	mutex_unlock(buf->mutex);
65 }
66 
67 // adjust buffer to multiple of mod bytes so reading in multiple always wraps on frame boundary
buf_adjust(struct buffer * buf,size_t mod)68 void buf_adjust(struct buffer *buf, size_t mod) {
69 	size_t size;
70 	mutex_lock(buf->mutex);
71 	size = ((unsigned)(buf->base_size / mod)) * mod;
72 	buf->readp  = buf->buf;
73 	buf->writep = buf->buf;
74 	buf->wrap   = buf->buf + size;
75 	buf->size   = size;
76 	mutex_unlock(buf->mutex);
77 }
78 
79 // called with mutex locked to resize, does not retain contents, reverts to original size if fails
_buf_resize(struct buffer * buf,size_t size)80 void _buf_resize(struct buffer *buf, size_t size) {
81 	free(buf->buf);
82 	buf->buf = malloc(size);
83 	if (!buf->buf) {
84 		size    = buf->size;
85 		buf->buf= malloc(size);
86 		if (!buf->buf) {
87 			size = 0;
88 		}
89 	}
90 	buf->readp  = buf->buf;
91 	buf->writep = buf->buf;
92 	buf->wrap   = buf->buf + size;
93 	buf->size   = size;
94 	buf->base_size = size;
95 }
96 
buf_init(struct buffer * buf,size_t size)97 void buf_init(struct buffer *buf, size_t size) {
98 	buf->buf    = malloc(size);
99 	buf->readp  = buf->buf;
100 	buf->writep = buf->buf;
101 	buf->wrap   = buf->buf + size;
102 	buf->size   = size;
103 	buf->base_size = size;
104 	mutex_create_p(buf->mutex);
105 }
106 
buf_destroy(struct buffer * buf)107 void buf_destroy(struct buffer *buf) {
108 	if (buf->buf) {
109 		free(buf->buf);
110 		buf->buf = NULL;
111 		buf->size = 0;
112 		buf->base_size = 0;
113 		mutex_destroy(buf->mutex);
114 	}
115 }
116