diff --git a/src/meson.build b/src/meson.build index 7d256e126..ff27f6f73 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,6 @@ pipewire_jack_sources = [ 'pipewire-jack.c', + 'ringbuffer.c', ] pipewire_jack_c_args = [ @@ -10,8 +11,9 @@ pipewire_jack_c_args = [ #optional dependencies jack_dep = dependency('jack', version : '>= 1.9.10', required : false) -pipewire_jack = shared_library('jack-pipewire', +pipewire_jack = shared_library('jack', pipewire_jack_sources, + soversion : 0, c_args : pipewire_jack_c_args, include_directories : [configinc], dependencies : [pipewire_dep, jack_dep], diff --git a/src/ringbuffer.c b/src/ringbuffer.c new file mode 100644 index 000000000..3ec9e28b1 --- /dev/null +++ b/src/ringbuffer.c @@ -0,0 +1,283 @@ +/* PipeWire + * Copyright (C) 2018 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include + +jack_ringbuffer_t *jack_ringbuffer_create(size_t sz) +{ + int power_of_two; + jack_ringbuffer_t *rb; + + rb = calloc(1, sizeof(jack_ringbuffer_t)); + if (rb == NULL) + return NULL; + + for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++); + + rb->size = 1 << power_of_two; + rb->size_mask = rb->size - 1; + if ((rb->buf = calloc(1, rb->size)) == NULL) { + free (rb); + return NULL; + } + rb->mlocked = 0; + + return rb; +} + +void jack_ringbuffer_free(jack_ringbuffer_t *rb) +{ +#ifdef USE_MLOCK + if (rb->mlocked) + munlock (rb->buf, rb->size); +#endif /* USE_MLOCK */ + free (rb->buf); + free (rb); +} + +void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb, + jack_ringbuffer_data_t *vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = rb->write_ptr; + 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) { + vec[0].buf = &(rb->buf[r]); + vec[0].len = rb->size - r; + vec[1].buf = rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } else { + vec[0].buf = &(rb->buf[r]); + vec[0].len = free_cnt; + vec[1].len = 0; + } +} + +void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb, + jack_ringbuffer_data_t *vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = rb->write_ptr; + 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) { + vec[0].buf = &(rb->buf[w]); + vec[0].len = rb->size - w; + vec[1].buf = rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } else { + vec[0].buf = &(rb->buf[w]); + vec[0].len = free_cnt; + vec[1].len = 0; + } +} + +size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + + if ((free_cnt = jack_ringbuffer_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); + rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask; + if (n2) { + memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2); + rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask; + } + return to_read; +} + +size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + size_t tmp_read_ptr; + + tmp_read_ptr = rb->read_ptr; + + if ((free_cnt = jack_ringbuffer_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); + tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask; + + if (n2) + memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2); + + return to_read; +} + +void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt) +{ + size_t tmp = (rb->read_ptr + cnt) & rb->size_mask; + rb->read_ptr = tmp; +} + +size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb) +{ + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + + if (w > r) + return w - r; + else + return (w - r + rb->size) & rb->size_mask; +} + +int jack_ringbuffer_mlock(jack_ringbuffer_t *rb) +{ +#ifdef USE_MLOCK + if (mlock (rb->buf, rb->size)) + return -1; +#endif /* USE_MLOCK */ + rb->mlocked = 1; + return 0; +} + +void jack_ringbuffer_reset(jack_ringbuffer_t *rb) +{ + rb->read_ptr = 0; + rb->write_ptr = 0; + memset(rb->buf, 0, rb->size); +} + +void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz) +{ + rb->size = sz; + rb->size_mask = rb->size - 1; + rb->read_ptr = 0; + rb->write_ptr = 0; +} + +size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, + size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + + if ((free_cnt = jack_ringbuffer_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); + rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask; + if (n2) { + memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2); + rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask; + } + return to_write; +} + +void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt) +{ + size_t tmp = (rb->write_ptr + cnt) & rb->size_mask; + rb->write_ptr = tmp; +} + +size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb) +{ + size_t w, r; + + w = rb->write_ptr; + 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; +}