buffer.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. // fifo bufffers
  22. #define _GNU_SOURCE
  23. #include "squeezelite.h"
  24. // _* called with muxtex locked
  25. inline unsigned _buf_used(struct buffer *buf) {
  26. return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->size - (buf->readp - buf->writep);
  27. }
  28. unsigned _buf_space(struct buffer *buf) {
  29. return buf->size - _buf_used(buf) - 1; // reduce by one as full same as empty otherwise
  30. }
  31. unsigned _buf_cont_read(struct buffer *buf) {
  32. return buf->writep >= buf->readp ? buf->writep - buf->readp : buf->wrap - buf->readp;
  33. }
  34. unsigned _buf_cont_write(struct buffer *buf) {
  35. return buf->writep >= buf->readp ? buf->wrap - buf->writep : buf->readp - buf->writep;
  36. }
  37. void _buf_inc_readp(struct buffer *buf, unsigned by) {
  38. buf->readp += by;
  39. if (buf->readp >= buf->wrap) {
  40. buf->readp -= buf->size;
  41. }
  42. }
  43. void _buf_inc_writep(struct buffer *buf, unsigned by) {
  44. buf->writep += by;
  45. if (buf->writep >= buf->wrap) {
  46. buf->writep -= buf->size;
  47. }
  48. }
  49. void buf_flush(struct buffer *buf) {
  50. mutex_lock(buf->mutex);
  51. buf->readp = buf->buf;
  52. buf->writep = buf->buf;
  53. mutex_unlock(buf->mutex);
  54. }
  55. void _buf_flush(struct buffer *buf) {
  56. buf->readp = buf->buf;
  57. buf->writep = buf->buf;
  58. }
  59. // adjust buffer to multiple of mod bytes so reading in multiple always wraps on frame boundary
  60. void buf_adjust(struct buffer *buf, size_t mod) {
  61. size_t size;
  62. mutex_lock(buf->mutex);
  63. size = ((unsigned)(buf->base_size / mod)) * mod;
  64. buf->readp = buf->buf;
  65. buf->writep = buf->buf;
  66. buf->wrap = buf->buf + size;
  67. buf->size = size;
  68. mutex_unlock(buf->mutex);
  69. }
  70. // called with mutex locked to resize, does not retain contents, reverts to original size if fails
  71. void _buf_resize(struct buffer *buf, size_t size) {
  72. if (size == buf->size) return;
  73. free(buf->buf);
  74. buf->buf = malloc(size);
  75. if (!buf->buf) {
  76. size = buf->size;
  77. buf->buf= malloc(size);
  78. if (!buf->buf) {
  79. size = 0;
  80. }
  81. }
  82. buf->readp = buf->buf;
  83. buf->writep = buf->buf;
  84. buf->wrap = buf->buf + size;
  85. buf->size = size;
  86. buf->base_size = size;
  87. }
  88. void buf_init(struct buffer *buf, size_t size) {
  89. buf->buf = malloc(size);
  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. mutex_create_p(buf->mutex);
  96. }
  97. void buf_destroy(struct buffer *buf) {
  98. if (buf->buf) {
  99. free(buf->buf);
  100. buf->buf = NULL;
  101. buf->size = 0;
  102. buf->base_size = 0;
  103. mutex_destroy(buf->mutex);
  104. }
  105. }