source: roaraudio/libroar/buffer.c @ 3021:a7929173bb2c

Last change on this file since 3021:a7929173bb2c was 3021:a7929173bb2c, checked in by phi, 15 years ago

do not enlarge no-free buffers

File size: 10.6 KB
RevLine 
[0]1//buffer.c:
2
[690]3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
[0]35#include "libroar.h"
36
37int roar_buffer_new      (struct roar_buffer ** buf, size_t len) {
[1215]38 void * data;
39
[2976]40 if ((data = roar_mm_malloc(len)) == NULL) {
[1215]41  return -1;
42 }
43
44 if ( roar_buffer_new_no_ma(buf, len, data) == -1 ) {
[2976]45  roar_mm_free(data);
[1215]46  return -1;
47 }
48
49 if ( roar_buffer_set_flag(*buf, ROAR_BUFFER_FLAG_NOFREE, ROAR_BUFFER_RESET) == -1 ) {
50  roar_buffer_free(*buf);
[2976]51  roar_mm_free(data);
[1215]52  return -1;
53 }
54
55 return 0;
56}
57
58int roar_buffer_new_no_ma(struct roar_buffer ** buf, size_t len, void * data) { // no internal malloc
[0]59 struct roar_buffer * new;
60
61 ROAR_DBG("buffer_new(buf=%p, len=%i) = ?", buf, len);
62
[1215]63 if ( buf == NULL || data == NULL )
64  return -1;
65
[2976]66 if ((new = roar_mm_malloc(sizeof(struct roar_buffer))) == NULL) {
[0]67  *buf = NULL;
68  return -1;
69 }
70
[1215]71 new->data      = data;
72
73 new->flags     = ROAR_BUFFER_FLAG_NONE|ROAR_BUFFER_FLAG_NOFREE;
[0]74
75 new->user_data = new->data;
76
77 new->next      = NULL;
78
79 new->len       = len;
80 new->user_len  = len;
81 *buf           = new;
82
83 ROAR_DBG("buffer_new(buf=%p, len=%i): New buffer at %p", buf, len, new);
84
85 return 0;
86}
87
88int roar_buffer_free     (struct roar_buffer * buf) {
89 struct roar_buffer * next;
90
91 if ( buf == NULL )
92  return -1;
93
94 while ((next = buf->next)) {
[2976]95  if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
96   roar_mm_free(buf->data);
97
98  roar_mm_free(buf);
[0]99  buf = next;
100 }
101
[1215]102 if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
[2976]103  roar_mm_free(buf->data);
[1215]104
[2976]105 roar_mm_free(buf);
[0]106
107 return 0;
108}
109
110int roar_buffer_delete   (struct roar_buffer * buf, struct roar_buffer ** next) {
111 if ( buf == NULL ) {
112  if ( next != NULL )
113   *next = NULL;
114  return -1;
115 }
116
117 ROAR_DBG("buffer_delete(buf=%p, next=%p) = ?", buf, next);
118
119 if ( next != NULL )
120  *next = buf->next;
121
[2976]122 if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
123  roar_mm_free(buf->data);
124
125 roar_mm_free(buf);
[0]126
127 ROAR_DBG("buffer_delete(buf=%p, next=%p) = 0", buf, next);
128 return 0;
129}
130
131int roar_buffer_add      (struct roar_buffer * buf, struct roar_buffer *  next) {
[1953]132 unsigned int deep = 0;
133
[0]134 if ( buf == NULL )
135  return -1;
136
137 ROAR_DBG("buffer_add(buf=%p, next=%p) = ?", buf, next);
138
[3020]139 if ( buf->flags & ROAR_BUFFER_FLAG_RING )
140  return -1;
141
[1953]142 if ( buf == next ) {
143  ROAR_ERR("buffer_add(*): both pointer are of the same destination, This is a error in the application");
144  return -1;
145 }
146
[0]147 while ( buf->next != NULL ) {
[302]148  ROAR_DBG("buffer_add(*): buf=%p, next=%p (len=%i)", buf, buf->next, buf->user_len);
[0]149//  ROAR_DBG("buffer_add(): buf=%p, buf->next=%p", buf, buf->next);
150  buf = buf->next;
[1953]151  deep++;
152
153  if ( buf == next ) {
154   ROAR_ERR("buffer_add(*): Can not add buffer: loop detected at deep %u. This is a error in the application", deep);
155  }
[0]156 }
157
158 buf->next = next;
159
[1953]160 ROAR_DBG("buffer_add(*): adding buffer at deep %u", deep);
161
[0]162 return 0;
163}
164
165int roar_buffer_get_next (struct roar_buffer *  buf, struct roar_buffer ** next) {
166 if ( buf == NULL )
167  return -1;
168
169 *next = buf->next;
170
171 return 0;
172}
173
[3020]174int roar_buffer_ring_new (struct roar_buffer ** buf, size_t len, int free_running) {
175 struct roar_buffer * n;
176
177 if ( buf == NULL || len == 0 )
178  return -1;
179
180 // just to be sure:
181 *buf = NULL;
182
183 // currently we are limited to free running mode
184 if ( !free_running )
185  return -1;
186
187 if ( roar_buffer_new(&n, len) == -1 )
188  return -1;
189
190 n->flags |= ROAR_BUFFER_FLAG_RING;
191
192 if ( free_running )
193  n->flags |= ROAR_BUFFER_FLAG_FREE_RUNNING;
194
195 n->meta.ring.read_pos  = 0;
196 n->meta.ring.write_pos = 0;
197
198 memset(n->data, 0, n->len);
199
200 *buf = n;
201
202 return 0;
203}
204
[0]205int roar_buffer_get_data (struct roar_buffer *  buf, void   ** data) {
206 if ( buf == NULL )
207  return -1;
208
209 *data = buf->user_data;
210
211 return 0;
212}
213
214int roar_buffer_set_offset (struct roar_buffer *  buf, size_t off) {
215 if ( buf == NULL )
216  return -1;
217
218 buf->user_len  -= off;
219 buf->user_data += off;
220
221 return 0;
222}
223
[904]224int roar_buffer_shift_out (struct roar_buffer ** buf, void * data, size_t * len) {
225 size_t todo, cl;
226 struct roar_buffer * cur;
227 void * cd;
228
[996]229 if ( len == NULL || buf == NULL || data == NULL ) {
[2101]230  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid input", buf, data, (unsigned long)*len);
[904]231  return -1;
[996]232 }
[904]233
[996]234 if ( *buf == NULL ) {
235  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid pointer to buffer ring", buf, data, (unsigned long)len);
[904]236  return -1;
[996]237 }
[904]238
239 todo = *len;
240 cur  = *buf;
241
242 *len = 0;
243
[2066]244 while (todo && cur != NULL) {
[904]245  ROAR_DBG("roar_buffer_shift_out(*): todo=%u, cur=%p", (unsigned int) todo, cur);
246
247  if ( roar_buffer_get_len(cur, &cl) == -1 )
248   return -1;
249
250  if ( cl > todo ) {
251   if ( roar_buffer_get_data(cur, &cd) == -1 )
252    return -1;
253
254   cl = todo;
255
256   memcpy(data, cd, cl);
257   todo -= cl;
258   data += cl;
259   *len += cl;
260
261   if ( roar_buffer_set_offset(cur, cl) == -1 )
262    return -1;
263  } else {
264   if ( roar_buffer_get_data(cur, &cd) == -1 )
265    return -1;
266
267   memcpy(data, cd, cl);
268   todo -= cl;
269   data += cl;
270   *len += cl;
271
272   if ( roar_buffer_next(&cur) == -1 )
273    return -1;
274  }
275
276/*
277  if ( cur == NULL )
278   break;
279*/
280 }
281
282 *buf = cur;
283
[996]284 return 0;
[904]285}
286
[0]287int roar_buffer_set_meta (struct roar_buffer * buf, void *  meta) {
288 if ( buf == NULL )
289  return -1;
290
[2333]291 buf->meta.vp = meta;
[0]292
293 return 0;
294}
295
296int roar_buffer_get_meta (struct roar_buffer * buf, void ** meta) {
[2333]297 if ( buf == NULL || meta == NULL )
298  return -1;
299
300 *meta = buf->meta.vp;
301
302 return 0;
303}
304
305int roar_buffer_set_meta_i32(struct roar_buffer *  buf, int32_t    meta) {
[0]306 if ( buf == NULL )
307  return -1;
308
[2333]309 buf->meta.i32 = meta;
310
311 return 0;
312}
313
314int roar_buffer_get_meta_i32(struct roar_buffer *  buf, int32_t *  meta) {
315 if ( buf == NULL || meta == NULL )
316  return -1;
317
318 *meta = buf->meta.i32;
[0]319
320 return 0;
321}
322
323int roar_buffer_set_len  (struct roar_buffer *  buf, size_t    len) {
[2334]324 size_t   totlen;
325 void   * newbuf;
326
[0]327 if ( buf == NULL )
328  return -1;
329
[2334]330 if ( len > buf->user_len ) {
[3021]331  // we can only enlage a buffer if it's one of our own memory segments
332  if ( buf->flags & ROAR_BUFFER_FLAG_NOFREE )
333   return -1;
334
[2334]335  totlen = buf->len - buf->user_len + len;
[3021]336  newbuf = roar_mm_realloc(buf->data, totlen);
[2334]337  if ( newbuf == NULL )
338   return -1;
339
340  buf->data = newbuf;
341  buf->user_len = len;
342 } else {
343  buf->user_len = len;
344 }
[0]345
346 return 0;
347}
348
349int roar_buffer_get_len  (struct roar_buffer *  buf, size_t *  len) {
350 if ( buf == NULL )
351  return -1;
352
353 *len = buf->user_len;
354
355 return 0;
356}
357
[1215]358int roar_buffer_set_flag (struct roar_buffer *  buf, int flag, int reset) {
359 if ( buf == NULL )
360  return -1;
361
362 buf->flags |= flag;
363
364 if ( reset )
365  buf->flags -= flag;
366
367 return 0;
368}
369
370int roar_buffer_get_flag (struct roar_buffer *  buf, int flag) {
371 if ( buf == NULL )
372  return -1;
373
374 return buf->flags & flag;
375}
376
[46]377int roar_buffer_duplicate (struct roar_buffer *  buf, struct roar_buffer ** copy) {
378 struct roar_buffer *  cur = buf;
379 struct roar_buffer *  new;
[48]380 void * od, * nd;
[46]381
382 *copy = NULL;
383
384 while (cur) {
385  if ( roar_buffer_new(&new, cur->user_len) == -1 ) {
386   roar_buffer_free(*copy);
387   return -1;
388  }
389
390  if ( *copy == NULL )
391   *copy = new;
392
[48]393  roar_buffer_get_data(cur, &od);
394  roar_buffer_get_data(new, &nd);
395  memcpy(nd, od, cur->user_len);
396
[46]397  roar_buffer_add(*copy, new);
398
399  cur = cur->next;
400 }
401 return 0;
402}
403
[7]404int roar_buffer_ring_stats (struct roar_buffer *  buf, struct roar_buffer_stats * stats) {
405 if ( buf == NULL )
406  return -1;
407
408 stats->parts        = 0;
409 stats->bytes        = 0;
410 stats->memory_usage = 0;
411
412 while (buf) {
413  stats->parts++;
414  stats->bytes        += buf->user_len;
415  stats->memory_usage += buf->len + sizeof(struct roar_buffer);
416  buf = buf->next;
417 }
418
419 return 0;
420}
421
[3020]422int roar_buffer_ring_read  (struct roar_buffer *  buf, void * data, size_t * len) {
423 if ( buf == NULL || len == NULL )
424  return -1;
425
426 if ( data == NULL && *len != 0 )
427  return -1;
428
429 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) )
430  return -1;
431
432 if ( *len == 0 )
433  return 0;
434
435 // we may handle this later:
436 if ( *len > buf->user_len )
437  return -1;
438
439 if ( buf->meta.ring.read_pos >= buf->user_len )
440  buf->meta.ring.read_pos -= buf->user_len;
441
442 if ( (*len + buf->meta.ring.read_pos) > buf->user_len ) {
443  // wraped mode:
444  memcpy(data, buf->user_data+buf->meta.ring.read_pos, buf->user_len - buf->meta.ring.read_pos);
445  memcpy(data, buf->user_data, *len + buf->meta.ring.read_pos - buf->user_len);
446
447  buf->meta.ring.read_pos += *len;
448  buf->meta.ring.read_pos -= buf->user_len;
449  return 0;
450 } else {
451  // unwarped mode:
452  memcpy(data, buf->user_data+buf->meta.ring.read_pos, *len);
453  buf->meta.ring.read_pos += *len;
454  return 0;
455 }
456
457 return -1;
458}
459
460int roar_buffer_ring_write (struct roar_buffer *  buf, void * data, size_t * len) {
461 if ( buf == NULL || len == NULL )
462  return -1;
463
464 if ( data == NULL && *len != 0 )
465  return -1;
466
467 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) )
468  return -1;
469
470 if ( *len == 0 )
471  return 0;
472
473 // we may handle this later:
474 if ( *len > buf->user_len )
475  return -1;
476
477 if ( buf->meta.ring.write_pos >= buf->user_len )
478  buf->meta.ring.write_pos -= buf->user_len;
479
480 if ( (*len + buf->meta.ring.write_pos) > buf->user_len ) {
481  // wraped mode:
482  memcpy(buf->user_data+buf->meta.ring.write_pos, data, buf->user_len - buf->meta.ring.write_pos);
483  memcpy(buf->user_data, data, *len + buf->meta.ring.write_pos - buf->user_len);
484
485  buf->meta.ring.write_pos += *len;
486  buf->meta.ring.write_pos -= buf->user_len;
487  return 0;
488 } else {
489  // unwarped mode:
490  memcpy(buf->user_data+buf->meta.ring.write_pos, data, *len);
491  buf->meta.ring.write_pos += *len;
492  return 0;
493 }
494
495 return -1;
496}
497
[0]498//ll
Note: See TracBrowser for help on using the repository browser.