source: roaraudio/libroar/buffer.c @ 4903:1a9db57bf503

Last change on this file since 4903:1a9db57bf503 was 4903:1a9db57bf503, checked in by phi, 13 years ago

check if we support some kind of data format type

File size: 16.5 KB
Line 
1//buffer.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38struct roar_buffer_ring {
39 size_t read_pos;
40 size_t write_pos;
41};
42
43struct roar_buffer {
44 size_t               refc;
45 size_t               len;
46 size_t               user_len;
47 int                  flags;
48 void               * data;
49 void               * user_data;
50 union {
51  void                    * vp;
52  int32_t                   i32;
53  struct roar_buffer_ring   ring;
54 }                    meta;
55 int                  type;
56 struct roar_buffer * next;
57};
58
59int roar_buffer_new_data (struct roar_buffer ** buf, size_t len, void ** data) {
60 void * bufdata;
61
62 if ((bufdata = roar_mm_malloc(len)) == NULL) {
63  return -1;
64 }
65
66 if ( roar_buffer_new_no_ma(buf, len, bufdata) == -1 ) {
67  roar_mm_free(bufdata);
68  return -1;
69 }
70
71 if ( roar_buffer_set_flag(*buf, ROAR_BUFFER_FLAG_NOFREE, ROAR_BUFFER_RESET) == -1 ) {
72  roar_buffer_free(*buf);
73  roar_mm_free(bufdata);
74  return -1;
75 }
76
77 if ( data != NULL )
78  *data = bufdata;
79
80 return 0;
81}
82
83int roar_buffer_new_no_ma(struct roar_buffer ** buf, size_t len, void * data) { // no internal malloc
84 struct roar_buffer * new;
85
86 ROAR_DBG("buffer_new(buf=%p, len=%i) = ?", buf, len);
87
88 if ( buf == NULL || data == NULL )
89  return -1;
90
91 if ((new = roar_mm_malloc(sizeof(struct roar_buffer))) == NULL) {
92  *buf = NULL;
93  return -1;
94 }
95
96 new->refc      =  1;
97
98 new->data      = data;
99
100 new->flags     = ROAR_BUFFER_FLAG_NONE|ROAR_BUFFER_FLAG_NOFREE;
101 new->type      = -1;
102
103 new->user_data = new->data;
104
105 new->next      = NULL;
106
107 new->len       = len;
108 new->user_len  = len;
109 *buf           = new;
110
111 ROAR_DBG("buffer_new(buf=%p, len=%i): New buffer at %p", buf, len, new);
112
113 return 0;
114}
115
116int roar_buffer_ref      (struct roar_buffer *  buf) {
117 if ( buf == NULL )
118  return -1;
119
120 buf->refc++;
121
122 return 0;
123}
124
125int roar_buffer_unref     (struct roar_buffer * buf) {
126 struct roar_buffer * next;
127
128 if ( buf == NULL )
129  return -1;
130
131 if ( buf->refc == 0 ) {
132  ROAR_WARN("roar_buffer_unref(buf=%p): Ref counter is wrong. assuming one.");
133  buf->refc = 1;
134 }
135
136 buf->refc--;
137
138 if ( buf->refc )
139  return 0;
140
141 while ((next = buf->next)) {
142  if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
143   roar_mm_free(buf->data);
144
145  roar_mm_free(buf);
146  buf = next;
147 }
148
149 if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
150  roar_mm_free(buf->data);
151
152 roar_mm_free(buf);
153
154 return 0;
155}
156
157int roar_buffer_delete   (struct roar_buffer * buf, struct roar_buffer ** next) {
158 if ( buf == NULL ) {
159  if ( next != NULL )
160   *next = NULL;
161  return -1;
162 }
163
164 ROAR_DBG("buffer_delete(buf=%p, next=%p) = ?", buf, next);
165
166 if ( next != NULL )
167  *next = buf->next;
168
169 if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
170  roar_mm_free(buf->data);
171
172 roar_mm_free(buf);
173
174 ROAR_DBG("buffer_delete(buf=%p, next=%p) = 0", buf, next);
175 return 0;
176}
177
178int roar_buffer_add      (struct roar_buffer * buf, struct roar_buffer *  next) {
179 unsigned int deep = 0;
180
181 if ( buf == NULL )
182  return -1;
183
184 ROAR_DBG("buffer_add(buf=%p, next=%p) = ?", buf, next);
185
186 if ( buf->flags & ROAR_BUFFER_FLAG_RING )
187  return -1;
188
189 if ( buf == next ) {
190  ROAR_ERR("buffer_add(*): both pointer are of the same destination, This is a error in the application");
191  return -1;
192 }
193
194 while ( buf->next != NULL ) {
195  ROAR_DBG("buffer_add(*): buf=%p, next=%p (len=%i)", buf, buf->next, buf->user_len);
196//  ROAR_DBG("buffer_add(): buf=%p, buf->next=%p", buf, buf->next);
197  buf = buf->next;
198  deep++;
199
200  if ( buf == next ) {
201   ROAR_ERR("buffer_add(*): Can not add buffer: loop detected at deep %u. This is a error in the application", deep);
202  }
203 }
204
205 buf->next = next;
206
207 ROAR_DBG("buffer_add(*): adding buffer at deep %u", deep);
208
209 return 0;
210}
211
212int roar_buffer_clear_next (struct roar_buffer *  buf) {
213 if ( buf == NULL )
214  return -1;
215
216 buf->next = NULL;
217
218 return 0;
219}
220
221int roar_buffer_get_next (struct roar_buffer *  buf, struct roar_buffer ** next) {
222 if ( buf == NULL )
223  return -1;
224
225 *next = buf->next;
226
227 return 0;
228}
229
230int roar_buffer_ring_new (struct roar_buffer ** buf, size_t len, int free_running) {
231 struct roar_buffer * n;
232
233 if ( buf == NULL || len == 0 )
234  return -1;
235
236 // just to be sure:
237 *buf = NULL;
238
239 if ( roar_buffer_new(&n, len) == -1 )
240  return -1;
241
242 n->flags |= ROAR_BUFFER_FLAG_RING;
243
244 if ( free_running )
245  n->flags |= ROAR_BUFFER_FLAG_FREE_RUNNING;
246
247 n->meta.ring.read_pos  = 0;
248 n->meta.ring.write_pos = 0;
249
250 memset(n->data, 0, n->len);
251
252 *buf = n;
253
254 return 0;
255}
256
257int roar_buffer_get_data (struct roar_buffer *  buf, void   ** data) {
258 if ( buf == NULL )
259  return -1;
260
261 *data = buf->user_data;
262
263 return 0;
264}
265
266int roar_buffer_set_offset (struct roar_buffer *  buf, size_t off) {
267 if ( buf == NULL )
268  return -1;
269
270 buf->user_len  -= off;
271 buf->user_data += off;
272
273 return 0;
274}
275
276int roar_buffer_shift_out (struct roar_buffer ** buf, void * data, size_t * len) {
277 size_t todo, cl;
278 struct roar_buffer * cur;
279 void * cd;
280
281 if ( len == NULL || buf == NULL || data == NULL ) {
282  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid input", buf, data, (unsigned long)*len);
283  return -1;
284 }
285
286 if ( *buf == NULL ) {
287  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid pointer to buffer ring", buf, data, (unsigned long)len);
288  return -1;
289 }
290
291 todo = *len;
292 cur  = *buf;
293
294 *len = 0;
295
296 while (todo && cur != NULL) {
297  ROAR_DBG("roar_buffer_shift_out(*): todo=%u, cur=%p", (unsigned int) todo, cur);
298
299  if ( roar_buffer_get_len(cur, &cl) == -1 )
300   return -1;
301
302  if ( cl > todo ) {
303   if ( roar_buffer_get_data(cur, &cd) == -1 )
304    return -1;
305
306   cl = todo;
307
308   memcpy(data, cd, cl);
309   todo -= cl;
310   data += cl;
311   *len += cl;
312
313   if ( roar_buffer_set_offset(cur, cl) == -1 )
314    return -1;
315  } else {
316   if ( roar_buffer_get_data(cur, &cd) == -1 )
317    return -1;
318
319   memcpy(data, cd, cl);
320   todo -= cl;
321   data += cl;
322   *len += cl;
323
324   if ( roar_buffer_next(&cur) == -1 )
325    return -1;
326  }
327
328/*
329  if ( cur == NULL )
330   break;
331*/
332 }
333
334 *buf = cur;
335
336 return 0;
337}
338
339int roar_buffer_set_meta (struct roar_buffer * buf, void *  meta) {
340 if ( buf == NULL )
341  return -1;
342
343 buf->meta.vp = meta;
344
345 return 0;
346}
347
348int roar_buffer_get_meta (struct roar_buffer * buf, void ** meta) {
349 if ( buf == NULL || meta == NULL )
350  return -1;
351
352 *meta = buf->meta.vp;
353
354 return 0;
355}
356
357int roar_buffer_set_meta_i32(struct roar_buffer *  buf, int32_t    meta) {
358 if ( buf == NULL )
359  return -1;
360
361 buf->meta.i32 = meta;
362
363 return 0;
364}
365
366int roar_buffer_get_meta_i32(struct roar_buffer *  buf, int32_t *  meta) {
367 if ( buf == NULL || meta == NULL )
368  return -1;
369
370 *meta = buf->meta.i32;
371
372 return 0;
373}
374
375int roar_buffer_set_type    (struct roar_buffer *  buf, int        type) {
376 if ( buf == NULL )
377  return -1;
378
379 switch (type) {
380  case ROAR_VIO_DFT_RAW:
381  case ROAR_VIO_DFT_PACKET:
382  case ROAR_VIO_DFT_UNFRAMED:
383   break;
384  default:
385    return -1;
386 }
387
388 buf->type = type;
389
390 return 0;
391}
392
393int roar_buffer_get_type    (struct roar_buffer *  buf, int     *  type) {
394 if ( buf == NULL || type == NULL )
395  return -1;
396
397 *type = buf->type;
398
399 return 0;
400}
401
402int roar_buffer_set_len  (struct roar_buffer *  buf, size_t    len) {
403 size_t   totlen;
404 void   * newbuf;
405
406 if ( buf == NULL )
407  return -1;
408
409 // handle specal case where user length is zero:
410 if ( len && !buf->user_len ) {
411  buf->user_data = buf->data;
412  buf->user_len  = buf->len;
413 }
414
415 if ( len > buf->user_len ) {
416  // we can only enlage a buffer if it's one of our own memory segments
417  if ( buf->flags & ROAR_BUFFER_FLAG_NOFREE )
418   return -1;
419
420  totlen = buf->len - buf->user_len + len;
421  newbuf = roar_mm_realloc(buf->data, totlen);
422  if ( newbuf == NULL )
423   return -1;
424
425  buf->data = newbuf;
426  buf->user_len = len;
427 } else {
428  buf->user_len = len;
429 }
430
431 return 0;
432}
433
434int roar_buffer_get_len  (struct roar_buffer *  buf, size_t *  len) {
435 if ( buf == NULL )
436  return -1;
437
438 *len = buf->user_len;
439
440 return 0;
441}
442
443int roar_buffer_set_flag (struct roar_buffer *  buf, int flag, int reset) {
444 if ( buf == NULL )
445  return -1;
446
447 buf->flags |= flag;
448
449 if ( reset )
450  buf->flags -= flag;
451
452 return 0;
453}
454
455int roar_buffer_get_flag (struct roar_buffer *  buf, int flag) {
456 if ( buf == NULL )
457  return -1;
458
459 return buf->flags & flag;
460}
461
462int roar_buffer_duplicate (struct roar_buffer *  buf, struct roar_buffer ** copy) {
463 struct roar_buffer *  cur = buf;
464 struct roar_buffer *  new;
465 void * od, * nd;
466
467 *copy = NULL;
468
469 while (cur) {
470  if ( roar_buffer_new(&new, cur->user_len) == -1 ) {
471   roar_buffer_free(*copy);
472   return -1;
473  }
474
475  if ( *copy == NULL )
476   *copy = new;
477
478  roar_buffer_get_data(cur, &od);
479  roar_buffer_get_data(new, &nd);
480  memcpy(nd, od, cur->user_len);
481
482  roar_buffer_add(*copy, new);
483
484  cur = cur->next;
485 }
486 return 0;
487}
488
489int roar_buffer_ring_stats (struct roar_buffer *  buf, struct roar_buffer_stats * stats) {
490 if ( buf == NULL )
491  return -1;
492
493 stats->parts        = 0;
494 stats->bytes        = 0;
495 stats->memory_usage = 0;
496
497 while (buf) {
498  stats->parts++;
499  stats->bytes        += buf->user_len;
500  stats->memory_usage += buf->len + sizeof(struct roar_buffer);
501  buf = buf->next;
502 }
503
504 return 0;
505}
506
507int roar_buffer_ring_read  (struct roar_buffer *  buf, void * data, size_t * len) {
508 struct roar_buffer_ring * ring;
509 size_t havelen;
510 size_t done;
511 size_t tmp;
512
513 if ( buf == NULL || len == NULL )
514  return -1;
515
516 if ( data == NULL && *len != 0 )
517  return -1;
518
519 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) )
520  return -1;
521
522 if ( *len == 0 )
523  return 0;
524
525 // we may handle this later:
526 if ( *len > buf->user_len )
527  return -1;
528
529 if ( (buf->flags & ROAR_BUFFER_FLAG_FREE_RUNNING) ) {
530  if ( buf->meta.ring.read_pos >= buf->user_len )
531   buf->meta.ring.read_pos -= buf->user_len;
532
533  if ( (*len + buf->meta.ring.read_pos) > buf->user_len ) {
534   // wraped mode:
535   memcpy(data, buf->user_data+buf->meta.ring.read_pos, buf->user_len - buf->meta.ring.read_pos);
536   memcpy(data, buf->user_data, *len + buf->meta.ring.read_pos - buf->user_len);
537 
538   buf->meta.ring.read_pos += *len;
539   buf->meta.ring.read_pos -= buf->user_len;
540   return 0;
541  } else {
542   // unwarped mode:
543   memcpy(data, buf->user_data+buf->meta.ring.read_pos, *len);
544   buf->meta.ring.read_pos += *len;
545   return 0;
546  }
547 } else {
548  ring = &(buf->meta.ring);
549
550  if ( ring->read_pos == ring->write_pos ) {
551   *len = 0;
552   return 0;
553  } else if ( ring->read_pos < ring->write_pos ) {
554   havelen = ring->write_pos - ring->read_pos;
555
556   if ( havelen > *len )
557    havelen = *len;
558
559   memcpy(data, buf->user_data+ring->read_pos, havelen);
560   ring->read_pos += havelen;
561
562   *len = havelen;
563   return 0;
564  } else { // write_pos < read_pos
565   done = 0;
566
567   // first pass: use data up to end of buffer
568
569   havelen = buf->user_len - ring->read_pos;
570
571   if ( havelen > *len )
572    havelen = *len;
573
574   memcpy(data, buf->user_data+ring->read_pos, havelen);
575   ring->read_pos += havelen;
576
577   done += havelen;
578
579   if ( ring->read_pos == buf->user_len ) {
580    ring->read_pos = 0;
581   }
582
583   // second pass: use data from strat of buffer to write pointer
584
585   if ( *len > done ) {
586    tmp = *len - done;
587    if ( roar_buffer_ring_read(buf, data+done, &tmp) == 0 ) {
588     done += tmp;
589    }
590   }
591
592   *len = done;
593   return 0;
594  }
595
596  return -1;
597 }
598
599 return -1;
600}
601
602int roar_buffer_ring_write (struct roar_buffer *  buf, void * data, size_t * len) {
603 struct roar_buffer_ring * ring;
604 size_t havelen;
605 size_t done;
606 size_t tmp;
607
608 ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
609
610 if ( buf == NULL || len == NULL )
611  return -1;
612
613 if ( data == NULL && *len != 0 )
614  return -1;
615
616 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) )
617  return -1;
618
619 if ( *len == 0 )
620  return 0;
621
622 // we may handle this later:
623 if ( *len > buf->user_len )
624  return -1;
625
626 if ( (buf->flags & ROAR_BUFFER_FLAG_FREE_RUNNING) ) {
627  if ( buf->meta.ring.write_pos >= buf->user_len )
628   buf->meta.ring.write_pos -= buf->user_len;
629
630  if ( (*len + buf->meta.ring.write_pos) > buf->user_len ) {
631   // wraped mode:
632   memcpy(buf->user_data+buf->meta.ring.write_pos, data, buf->user_len - buf->meta.ring.write_pos);
633   memcpy(buf->user_data, data, *len + buf->meta.ring.write_pos - buf->user_len);
634
635   buf->meta.ring.write_pos += *len;
636   buf->meta.ring.write_pos -= buf->user_len;
637   return 0;
638  } else {
639   // unwarped mode:
640   memcpy(buf->user_data+buf->meta.ring.write_pos, data, *len);
641   buf->meta.ring.write_pos += *len;
642   return 0;
643  }
644 } else {
645  ring = &(buf->meta.ring);
646  done = 0;
647
648  ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p): write_pos=%u, read_pos=%u, user_len=%u", buf, data, len, (unsigned int)ring->write_pos, (unsigned int)ring->read_pos, (unsigned int)buf->user_len);
649
650  if ( ring->write_pos >= ring->read_pos ) {
651   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
652
653   havelen = buf->user_len - ring->write_pos;
654
655   if ( ring->read_pos == 0 )
656    havelen--;
657
658   if ( havelen > *len )
659    havelen = *len;
660
661   memcpy(buf->user_data+ring->write_pos, data, havelen);
662
663   done += havelen;
664   ring->write_pos += havelen;
665
666   if ( ring->write_pos == buf->user_len )
667    ring->write_pos = 0;
668
669   if ( *len > done && ring->read_pos != 0 ) {
670    tmp = *len - done;
671    if ( roar_buffer_ring_write(buf, data+done, &tmp) == 0 ) {
672     done += tmp;
673    }
674   }
675
676   *len = done;
677   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = 0", buf, data, len);
678   return 0;
679  } else {
680   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
681
682   // test for buffer-is-full:
683   if ( (ring->write_pos + 1) == ring->read_pos ) {
684    *len = 0;
685    ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = 0", buf, data, len);
686    return 0;
687   }
688
689   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
690
691   havelen = ring->read_pos - ring->write_pos - 1;
692
693   if ( havelen > *len )
694    havelen = *len;
695
696   memcpy(buf->user_data+ring->write_pos, data, havelen);
697
698   ring->write_pos += havelen;
699   *len = havelen;
700
701   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = 0", buf, data, len);
702   return 0;
703  }
704
705  return -1;
706 }
707
708 return -1;
709}
710
711int roar_buffer_ring_avail(struct roar_buffer *  buf, size_t * readlen, size_t * writelen) {
712 struct roar_buffer_ring * ring;
713 size_t have;
714
715 if ( buf == NULL )
716  return -1;
717
718 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) )
719  return -1;
720
721 ring = &(buf->meta.ring);
722
723 ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p) = ?", buf, readlen, writelen);
724
725 if ( readlen != NULL ) {
726  have = 0;
727
728  if ( ring->write_pos >= ring->read_pos ) {
729   have  = ring->write_pos - ring->read_pos;
730  } else {
731   have  = buf->user_len - ring->read_pos;
732   have += ring->write_pos;
733   have -= 1;
734  }
735
736  *readlen = have;
737  ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p): readlen=%llu", buf, readlen, writelen, (unsigned long long int)have);
738 }
739
740 if ( writelen != NULL ) {
741  have = 0;
742
743  if ( ring->read_pos > ring->write_pos ) {
744   have  = ring->read_pos - ring->write_pos - 1;
745  } else {
746   have  = buf->user_len - ring->write_pos;
747   have += ring->read_pos;
748   have -= 1;
749  }
750
751  *writelen = have;
752  ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p): readlen=%llu", buf, readlen, writelen, (unsigned long long int)have);
753 }
754
755 ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p) = 0", buf, readlen, writelen);
756
757 return 0;
758}
759
760int roar_buffer_ring_reset(struct roar_buffer *  buf) {
761 if ( buf == NULL )
762  return -1;
763
764 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) )
765  return -1;
766
767 buf->meta.ring.read_pos = buf->meta.ring.write_pos = 0;
768
769 return 0;
770}
771
772//ll
Note: See TracBrowser for help on using the repository browser.