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