source: roaraudio/roard/streams.c @ 981:892b34984ecd

Last change on this file since 981:892b34984ecd was 981:892b34984ecd, checked in by phi, 15 years ago

added fc object to ss object, not used yet, update pos on monetoring/output streams

File size: 20.6 KB
Line 
1//streams.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of roard 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 *  RoarAudio 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 */
24
25#include "roard.h"
26
27int streams_init (void) {
28 int i;
29
30 for (i = 0; i < ROAR_STREAMS_MAX; i++)
31  g_streams[i] = NULL;
32
33 return 0;
34}
35
36int streams_free (void) {
37 int i;
38
39 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
40  if ( g_streams[i] != NULL ) {
41   streams_delete(i);
42  }
43 }
44
45 return 0;
46}
47
48
49int streams_new    (void) {
50 int i, j;
51 struct roar_stream        * n = NULL;
52 struct roar_stream_server * s = NULL;
53
54 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
55  if ( g_streams[i] == NULL ) {
56   s = ROAR_STREAM_SERVER(n = ROAR_STREAM(malloc(sizeof(struct roar_stream_server))));
57   if ( n == NULL ) {
58    ROAR_ERR("streams_new(void): can not allocate memory for new stream: %s", strerror(errno));
59    ROAR_DBG("streams_new(void) = -1");
60    return -1;
61   }
62
63   n->id         = i;
64   n->fh         = -1;
65//   n->pos_rel_id = i;
66   n->database   = NULL;
67   n->dataoff    = NULL;
68   n->datalen    = 0;
69   n->offset     = 0;
70   n->pos        = 0;
71
72   s->client          = -1;
73   s->socktype        = ROAR_SOCKET_TYPE_UNKNOWN;
74   s->buffer          = NULL;
75   s->need_extra      =  0;
76   s->output          = NULL;
77   s->is_new          =  1;
78   s->codecfilter     = -1;
79   s->pre_underruns   =  0;
80   s->post_underruns  =  0;
81   s->codec_orgi      = -1;
82   s->primary         =  0;
83
84   s->mixer.scale     = 65535;
85   s->mixer.rpg_mul   = 1;
86   s->mixer.rpg_div   = 1;
87   for (j = 0; j < ROAR_MAX_CHANNELS; j++)
88    s->mixer.mixer[j] = 65535;
89
90   for (j = 0; j < ROAR_META_MAX_PER_STREAM; j++) {
91    s->meta[j].type   = ROAR_META_TYPE_NONE;
92    s->meta[j].key[0] = 0;
93    s->meta[j].value  = NULL;
94   }
95
96   roar_vio_init_calls(&(s->vio));
97   s->driver_id = -1;
98
99   roardsp_fchain_init(&(s->fc));
100
101   g_streams[i] = s;
102   ROAR_DBG("streams_new(void): n->id=%i", n->id);
103   ROAR_DBG("streams_new(void) = %i", i);
104   return i;
105  }
106 }
107
108 return -1;
109}
110
111int streams_delete (int id) {
112 struct roar_stream_server * s;
113 int prim;
114
115 if ( (s = g_streams[id]) == NULL )
116  return 0;
117
118 ROAR_DBG("streams_delete(id=%i) = ?", id);
119 ROAR_DBG("streams_delete(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(s)->id);
120
121 if ( s->codecfilter != -1 ) {
122  codecfilter_close(s->codecfilter_inst, s->codecfilter);
123  s->codecfilter_inst = NULL;
124  s->codecfilter = -1;
125 }
126
127 if ( s->driver_id != -1 ) {
128  driver_closevio(&(s->vio), s->driver_id);
129  roar_vio_init_calls(&(s->vio));
130  s->driver_id = -1;
131 }
132
133 roardsp_fchain_uninit(&(s->fc));
134
135 if ( s->client != -1 ) {
136  ROAR_DBG("streams_delete(id=%i): Stream is owned by client %i", id, g_streams[id]->client);
137  client_stream_delete(s->client, id);
138 }
139
140 if ( s->buffer != NULL )
141  roar_buffer_free(s->buffer);
142
143 if ( s->output != NULL )
144  free(s->output);
145
146 if ( ROAR_STREAM(s)->fh != -1 )
147  close(ROAR_STREAM(s)->fh);
148
149 prim = s->primary;
150
151 free(s);
152
153 g_streams[id] = NULL;
154
155 if ( prim ) {
156  alive = 0;
157  clean_quit();
158 }
159
160 ROAR_DBG("streams_delete(id=%i) = 0", id);
161 return 0;
162}
163
164int streams_set_client (int id, int client) {
165 if ( g_streams[id] == NULL )
166  return -1;
167
168 ROAR_DBG("streams_set_client(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(g_streams[id])->id);
169 g_streams[id]->client = client;
170
171 return 0;
172}
173
174int streams_get_client (int id) {
175 if ( g_streams[id] == NULL )
176  return -1;
177
178 return g_streams[id]->client;
179}
180
181
182int streams_set_fh     (int id, int fh) {
183 int dir;
184
185 if ( g_streams[id] == NULL )
186  return -1;
187
188 ROAR_DBG("streams_set_fh(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(g_streams[id])->id);
189
190 ROAR_STREAM(g_streams[id])->fh = fh;
191
192 if ( codecfilter_open(&(g_streams[id]->codecfilter_inst), &(g_streams[id]->codecfilter), NULL,
193                  ROAR_STREAM(g_streams[id])->info.codec, g_streams[id]) == -1 ) {
194  return streams_delete(id);
195 }
196
197 if ( fh == -1 ) { // yes, this is valid, indecats full vio!
198  return 0;
199 }
200
201// roar_socket_recvbuf(fh, ROAR_OUTPUT_CALC_OUTBUFSIZE( &(ROAR_STREAM(g_streams[id])->info) )); // set recv buffer to minimum
202
203 dir = ROAR_STREAM(g_streams[id])->dir;
204
205 if ( dir == ROAR_DIR_MONITOR || dir == ROAR_DIR_RECORD || dir == ROAR_DIR_OUTPUT ) {
206  shutdown(fh, SHUT_RD);
207 }
208
209 if ( dir == ROAR_DIR_FILTER ) {
210  return 0;
211 } else {
212  return roar_socket_nonblock(fh, ROAR_SOCKET_NONBLOCK);
213 }
214}
215
216int streams_get_fh     (int id) {
217 if ( id < 0 )
218  return -1;
219
220 if ( g_streams[id] == NULL )
221  return -1;
222
223 return ROAR_STREAM(g_streams[id])->fh;
224}
225
226int streams_get    (int id, struct roar_stream_server ** stream) {
227 if ( g_streams[id] == NULL )
228  return -1;
229
230 *stream = g_streams[id];
231
232 return 0;
233}
234
235int streams_set_socktype (int id, int socktype) {
236 if ( g_streams[id] == NULL )
237  return -1;
238
239 g_streams[id]->socktype = socktype;
240
241 return 0;
242}
243
244int streams_get_socktype (int id) {
245 if ( g_streams[id] == NULL )
246  return -1;
247
248 return g_streams[id]->socktype;
249}
250
251int streams_set_primary (int id, int prim) {
252 if ( g_streams[id] == NULL )
253  return -1;
254
255 g_streams[id]->primary = prim;
256
257 return 0;
258}
259
260int streams_mark_primary (int id) {
261 return streams_set_primary(id, 1);
262}
263int streams_get_outputbuffer  (int id, void ** buffer, size_t size) {
264 if ( g_streams[id] == NULL )
265  return -1;
266
267 // output buffer size does never change.
268 if ( g_streams[id]->output != NULL ) {
269  *buffer = g_streams[id]->output;
270  return 0;
271 }
272
273 if ( (g_streams[id]->output = malloc(size)) == NULL ) {
274  ROAR_ERR("streams_get_outputbuffer(*): Can not alloc: %s", strerror(errno));
275  return -1;
276 }
277
278 *buffer = g_streams[id]->output;
279
280 return 0;
281}
282
283int streams_fill_mixbuffer (int id, struct roar_audio_info * info) {
284 // TODO: decide: is this the most complex, hacked, un-understadable,
285 //               un-writeable and even worse: un-readable
286 //               function in the whole project?
287 size_t todo = ROAR_OUTPUT_CALC_OUTBUFSIZE(info);
288 size_t needed = todo;
289 size_t todo_in;
290 size_t len, outlen;
291 size_t mul = 1, div = 1;
292 void * rest = NULL;
293 void * in   = NULL;
294 struct roar_buffer     * buf;
295 struct roar_audio_info * stream_info;
296 struct roar_stream_server * stream = g_streams[id];
297 int is_the_same = 0;
298
299 if ( g_streams[id] == NULL )
300  return -1;
301
302 if ( streams_get_outputbuffer(id, &rest, todo) == -1 ) {
303  return -1;
304 }
305
306 if ( rest == NULL ) {
307  return -1;
308 }
309
310 // set up stream_info
311
312 stream_info = &(ROAR_STREAM(stream)->info);
313
314 // calc todo_in
315 todo_in = ROAR_OUTPUT_CALC_OUTBUFSIZE(stream_info);
316
317 // calc mul and div:
318 mul = todo    / todo_in;
319 div = todo_in / todo;
320
321 if ( mul == 0 ) {
322  mul = 1;
323 } else {
324  div = 1;
325 }
326
327 ROAR_DBG("streams_fill_mixbuffer(*): mul=%i, div=%i", mul, div);
328
329 ROAR_DBG("streams_fill_mixbuffer(*): rest=%p, todo=%i->%i (in->out)", rest, todo_in, todo);
330 // are both (input and output) of same format?
331
332
333 ROAR_DBG("streams_fill_mixbuffer(*): stream_info:");
334 roar_debug_audio_info_print(stream_info);
335 ROAR_DBG("streams_fill_mixbuffer(*): info:");
336 roar_debug_audio_info_print(info);
337
338 is_the_same = stream_info->rate     == info->rate     && stream_info->bits  == info->bits &&
339               stream_info->channels == info->channels && stream_info->codec == info->codec;
340
341 ROAR_DBG("streams_fill_mixbuffer(*): is_the_same=%i", is_the_same);
342
343/* How it works:
344 *
345 * set a counter to the number of samples we need.
346 * loop until we have all samples done or no samples are
347 * left in our input buffer.
348 * If there a no samples left in the input buffer: fill the rest
349 * of the output buffer with zeros.
350 *
351 * The loop:
352 * get a buffer from the input.
353 * if it's bigger than needed, set an offset.
354 * The rest of the data:
355 * 0) convert endianness (codec) from remote to local...
356 * 1) change bits in of the samples
357 * 2) change sample rate
358 * 3) change the nummber of channels
359 * 4) insert into output buffer
360 */
361
362/*
363 // get our first buffer:
364
365 if ( stream_shift_buffer(id, &buf) == -1 ) {
366  return -1;
367 }
368
369 // first test for some basic simple cases...
370
371 if ( buf == NULL ) { // we habe nothing in input queue
372                      // we may memset() our output buffer OR
373                      // just return with -1 so we are going to
374                      // be ignored.
375  return -1;
376 }
377*/
378
379 while (todo) { // main loop
380  ROAR_DBG("streams_fill_mixbuffer(*): looping...");
381  // exit loop if nothing is left, even if we need more data..
382  if ( stream_shift_buffer(id, &buf) == -1 )
383   break;
384  if ( buf == NULL )
385   break;
386
387  // read the data for this loop...
388  roar_buffer_get_data(buf, &in);
389  roar_buffer_get_len(buf, &len);
390
391  ROAR_DBG("streams_fill_mixbuffer(*): len = %i", len);
392
393  if ( len > todo_in ) {
394   roar_buffer_set_offset(buf, todo_in);
395   len = todo_in;
396  } else {
397   roar_buffer_set_len(buf, 0); // queue for deletation
398  }
399
400  // we now have 'len' bytes in 'in'
401
402  // calc how much outlen this has...
403  outlen = (len * mul) / div;
404
405  ROAR_DBG("streams_fill_mixbuffer(*): outlen = %i, buf = %p, len = %i", outlen, in, len);
406
407  if ( is_the_same ) {
408/*
409 * 0) convert endianness (codec) from remote to local...
410 * 1) change bits in of the samples
411 * 2) change sample rate
412 * 3) change the nummber of channels
413   \\==> skiping,...
414 */
415   // * 4) insert into output buffer
416   ROAR_DBG("streams_fill_mixbuffer(*): memcpy: in->rest: %p -> %p", in, rest);
417   if ( memcpy(rest, in, len) != rest ) {
418    ROAR_ERR("streams_fill_mixbuffer(*): memcpy returned invalid pointer.");
419   }
420
421  } else {
422
423/*
424   // * 0) convert endianness (codec) from remote to local...
425   if ( stream_info->codec != info->codec ) {
426    // we neet to convert...
427    return -1;
428   }
429
430   // * 1) change bits in of the samples
431   if ( stream_info->bits != info->bits ) {
432    return -1;
433   }
434
435   // * 2) change sample rate
436   if ( stream_info->rate != info->rate ) {
437    return -1;
438   }
439
440   // * 3) change the nummber of channels
441   if ( stream_info->channels != info->channels ) {
442    return -1;
443   }
444
445   // * 4) insert into output buffer
446*/
447  // hey! we have roar_conv() :)
448
449  if ( roar_conv(rest, in, 8*len / stream_info->bits, stream_info, info) == -1 )
450   return -1;
451  }
452
453  if ( change_vol(rest, info->bits, rest, 8*outlen / info->bits, info->channels, &(stream->mixer)) == -1 )
454   return -1;
455
456  // we habe outlen bytes more...
457  todo    -= outlen;
458  rest    += outlen;
459  todo_in -= len;
460
461  roar_buffer_get_len(buf, &len);
462  ROAR_DBG("streams_fill_mixbuffer(*): New length of buffer %p is %i", buf, len);
463  if ( len == 0 ) {
464   roar_buffer_delete(buf, NULL);
465  } else {
466   stream_unshift_buffer(id, buf);
467  }
468 }
469
470//len = 0;
471//roar_buffer_get_len(buf, &len);
472
473/*
474 if ( len > 0 ) // we still have some data in this buffer, re-inserting it to the input buffers...
475  stream_unshift_buffer(id, buf);
476 else
477  buffer_delete(buf, NULL);
478*/
479
480 ROAR_STREAM(g_streams[id])->pos =
481      ROAR_MATH_OVERFLOW_ADD(ROAR_STREAM(g_streams[id])->pos,
482          ROAR_OUTPUT_CALC_OUTBUFSAMP(info, needed-todo));
483 //ROAR_WARN("stream=%i, pos=%u", id, ((struct roar_stream*)g_streams[id])->pos);
484
485 if ( todo > 0 ) { // zeroize the rest of the buffer
486  memset(rest, 0, todo);
487
488  if ( todo != ROAR_OUTPUT_CALC_OUTBUFSIZE(info) ) {
489   if ( g_streams[id]->is_new ) {
490    stream->pre_underruns++;
491   } else {
492    ROAR_WARN("streams_fill_mixbuffer(*): Underrun in stream: %u bytes missing, filling with zeros", (unsigned int)todo);
493    stream->post_underruns++;
494   }
495
496   stream->is_new = 0;
497  }
498 } else {
499  stream->is_new = 0;
500 }
501
502 return 0;
503}
504
505
506int streams_get_mixbuffers (void *** bufferlist, struct roar_audio_info * info, unsigned int pos) {
507 static void * bufs[ROAR_STREAMS_MAX+1];
508 int i;
509 int have = 0;
510
511 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
512  if ( g_streams[i] != NULL ) {
513   if ( ROAR_STREAM(g_streams[i])->dir != ROAR_DIR_PLAY && ROAR_STREAM(g_streams[i])->dir != ROAR_DIR_BIDIR )
514    continue;
515
516   if ( streams_get_outputbuffer(i, &bufs[have], ROAR_OUTPUT_CALC_OUTBUFSIZE(info)) == -1 ) {
517    ROAR_ERR("streams_get_mixbuffer(*): Can not alloc output buffer for stream %i, BAD!", i);
518    ROAR_ERR("streams_get_mixbuffer(*): Ignoring stream for this round.");
519    continue;
520   }
521   if ( streams_fill_mixbuffer(i, info) == -1 ) {
522    ROAR_ERR("streams_get_mixbuffer(*): Can not fill output buffer for stream %i, this should not happen", i);
523    continue;
524   }
525
526//   printf("D: bufs[have=%i] = %p\n", have, bufs[have]);
527
528   ROAR_DBG("streams_get_mixbuffers(*):  bufs[have] = %p", bufs[have]);
529   ROAR_DBG("streams_get_mixbuffers(*): *bufs[have] = 0x%08x...", *(uint32_t*)bufs[have]);
530
531   have++; // we have a new stream!
532  }
533 }
534
535 bufs[have] = NULL;
536 //printf("D: bufs[have=%i] = %p\n", have, bufs[have]);
537
538 ROAR_DBG("streams_get_mixbuffers(*): have = %i", have);
539
540 *bufferlist = bufs;
541 return have;
542}
543
544
545int stream_add_buffer  (int id, struct roar_buffer * buf) {
546 ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = ?", id, buf);
547
548 if ( g_streams[id] == NULL )
549  return -1;
550
551 if ( g_streams[id]->buffer == NULL ) {
552  g_streams[id]->buffer = buf;
553  ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = 0", id, buf);
554  return 0;
555 }
556
557 ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = ?", id, buf);
558 return roar_buffer_add(g_streams[id]->buffer, buf);
559}
560
561int stream_shift_buffer   (int id, struct roar_buffer ** buf) {
562 struct roar_buffer * next;
563
564 if ( g_streams[id] == NULL )
565  return -1;
566
567 if ( g_streams[id]->buffer == NULL ) {
568  *buf = NULL;
569  return 0;
570 }
571
572 roar_buffer_get_next(g_streams[id]->buffer, &next);
573
574 *buf                  = g_streams[id]->buffer;
575 g_streams[id]->buffer = next;
576
577 return 0;
578}
579int stream_unshift_buffer (int id, struct roar_buffer *  buf) {
580 if ( g_streams[id] == NULL )
581  return -1;
582
583 if ( g_streams[id]->buffer == NULL ) {
584  g_streams[id]->buffer = buf;
585  return 0;
586 }
587
588 buf->next = NULL;
589
590 roar_buffer_add(buf, g_streams[id]->buffer);
591
592 g_streams[id]->buffer = buf;
593
594 return 0;
595}
596
597int streams_check  (int id) {
598 int fh;
599 ssize_t req, realreq, done;
600 struct roar_stream        *   s;
601 struct roar_stream_server *  ss;
602 struct roar_buffer        *   b;
603 char                      * buf;
604
605 if ( g_streams[id] == NULL )
606  return -1;
607
608 ROAR_DBG("streams_check(id=%i) = ?", id);
609
610 s = ROAR_STREAM(ss = g_streams[id]);
611
612 if ( (fh = s->fh) == -1 )
613  return 0;
614
615 if ( s->dir != ROAR_DIR_PLAY && s->dir != ROAR_DIR_BIDIR )
616  return 0;
617
618 ROAR_DBG("streams_check(id=%i): fh = %i", id, fh);
619
620 req  = ROAR_OUTPUT_BUFFER_SAMPLES * s->info.channels * s->info.bits / 8; // optimal size
621 req += ss->need_extra; // bytes left we sould get....
622
623 if ( roar_buffer_new(&b, req) == -1 ) {
624  ROAR_ERR("streams_check(*): Can not alloc buffer space!");
625  ROAR_DBG("streams_check(*) = -1");
626  return -1;
627 }
628
629 roar_buffer_get_data(b, (void **)&buf);
630
631 ROAR_DBG("streams_check(id=%i): buffer is up and ready ;)", id);
632
633 if ( ss->codecfilter == -1 ) {
634  realreq = req;
635/*
636  req = read(fh, buf, req);
637  if ( req < realreq ) { // we can do this as the stream is in nonblocking mode!
638   if ( (realreq = read(fh, buf+req, realreq-req)) > 0 )
639    req += realreq;
640  }
641*/
642  done = 0;
643  while (req > 0 && done != realreq) {
644   if ( (req = stream_vio_s_read(ss, buf+done, realreq-done)) > 0 )
645    done += req;
646  }
647  req = done;
648 } else {
649  req = codecfilter_read(ss->codecfilter_inst, ss->codecfilter, buf, req);
650 }
651
652 if ( req > 0 ) {
653  ROAR_DBG("streams_check(id=%i): got %i bytes", id, req);
654
655  roar_buffer_set_len(b, req);
656
657  if ( stream_add_buffer(id, b) != -1 )
658   return 0;
659
660  ROAR_ERR("streams_check(id=%i): something is wrong, could not add buffer to stream!", id);
661  roar_buffer_free(b);
662 } else {
663  ROAR_DBG("streams_check(id=%i): read() = %i // errno: %s", id, req, strerror(errno));
664#ifdef ROAR_HAVE_LIBVORBISFILE
665  if ( errno != EAGAIN && errno != ESPIPE ) { // libvorbis file trys to seek a bit ofen :)
666#else
667  if ( errno != EAGAIN ) {
668#endif
669   ROAR_DBG("streams_check(id=%i): EOF!", id);
670   streams_delete(id);
671   ROAR_DBG("streams_check(id=%i) = 0", id);
672  }
673  roar_buffer_free(b);
674  return 0;
675 }
676
677
678 ROAR_DBG("streams_check(id=%i) = -1", id);
679 return -1;
680}
681
682
683int streams_send_mon   (int id) {
684// int fh;
685 struct roar_stream        *   s;
686 struct roar_stream_server *  ss;
687 void * obuf;
688 int    olen;
689 int    need_to_free = 0;
690
691 if ( g_streams[id] == NULL )
692  return -1;
693
694 ROAR_DBG("streams_send_mon(id=%i) = ?", id);
695
696 s = ROAR_STREAM((ss = g_streams[id]));
697
698/*
699 if ( (fh = s->fh) == -1 )
700  return 0;
701*/
702
703 if ( s->dir != ROAR_DIR_MONITOR && s->dir != ROAR_DIR_OUTPUT && s->dir != ROAR_DIR_BIDIR )
704  return 0;
705
706 if ( s->dir == ROAR_DIR_OUTPUT && g_standby )
707  return 0;
708
709 ROAR_DBG("streams_send_mon(id=%i): fh = %i", id, fh);
710
711 if ( s->info.channels != g_sa->channels || s->info.bits  != g_sa->bits ||
712      s->info.rate     != g_sa->rate     || s->info.codec != g_sa->codec  ) {
713  olen = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info)); // we hope g_output_buffer_len
714                                                  // is ROAR_OUTPUT_CALC_OUTBUFSIZE(g_sa) here
715  if ( (obuf = malloc(olen)) == NULL )
716   return -1;
717
718  need_to_free = 1;
719
720  ROAR_DBG("streams_send_mon(id=%i): obuf=%p, olen=%i", id, obuf, olen);
721
722  if ( roar_conv(obuf, g_output_buffer, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa, &(s->info)) == -1 ) {
723   free(obuf);
724   return -1;
725  }
726 } else {
727  obuf = g_output_buffer;
728  olen = g_output_buffer_len;
729 }
730
731 errno = 0;
732
733 if ( ss->codecfilter == -1 ) {
734  if ( stream_vio_s_write(ss, obuf, olen) == olen ) {
735   if ( need_to_free ) free(obuf);
736   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
737   return 0;
738  }
739 } else {
740  if ( codecfilter_write(ss->codecfilter_inst, ss->codecfilter, obuf, olen)
741            == olen ) {
742   if ( need_to_free ) free(obuf);
743   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
744   return 0;
745  } else { // we cann't retry on codec filetered streams
746   if ( need_to_free ) free(obuf);
747   streams_delete(id);
748   return -1;
749  }
750 }
751
752 if ( errno == EAGAIN ) {
753  // ok, the client blocks for a moment, we try to sleep a bit an retry in the hope not to
754  // make any gapes in any output because of this
755
756  usleep(100); // 0.1ms
757
758  if ( stream_vio_s_write(ss, obuf, olen) == olen ) {
759   if ( need_to_free ) free(obuf);
760   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
761   return 0;
762  }
763 }
764
765 // ug... error... delete stream!
766
767 if ( need_to_free ) free(obuf);
768 streams_delete(id);
769
770 return -1;
771}
772
773int streams_send_filter(int id) {
774 int fh;
775 int have = 0;
776 int len;
777 struct roar_stream        *   s;
778 struct roar_stream_server *  ss;
779
780 if ( g_streams[id] == NULL )
781  return -1;
782
783 ROAR_DBG("streams_send_filter(id=%i) = ?", id);
784
785 s = ROAR_STREAM(ss = g_streams[id]);
786
787 if ( (fh = s->fh) == -1 )
788  return 0;
789
790 if ( s->dir != ROAR_DIR_FILTER )
791  return 0;
792
793 ROAR_DBG("streams_send_filter(id=%i): fh = %i", id, fh);
794
795 if ( stream_vio_s_write(ss, g_output_buffer, g_output_buffer_len) == g_output_buffer_len ) {
796  while ( have < g_output_buffer_len ) {
797   if ( (len = stream_vio_s_read(ss, g_output_buffer+have, g_output_buffer_len-have)) < 1 ) {
798    streams_delete(id);
799    return -1;
800   }
801   have += len;
802  }
803  return 0;
804 }
805
806 // ug... error... delete stream!
807
808 streams_delete(id);
809
810 return -1;
811}
812
813
814// VIO:
815
816ssize_t stream_vio_read (int stream, void *buf, size_t count) {
817 struct roar_stream_server * s = g_streams[stream];
818
819 if ( !s )
820  return -1;
821
822 return stream_vio_s_read(s, buf, count);
823}
824
825ssize_t stream_vio_write(int stream, void *buf, size_t count) {
826 struct roar_stream_server * s = g_streams[stream];
827
828 if ( !s )
829  return -1;
830
831 return stream_vio_s_write(s, buf, count);
832}
833
834
835ssize_t stream_vio_s_read (struct roar_stream_server * stream, void *buf, size_t count) {
836  size_t len =  0;
837 ssize_t r   = -1;
838
839 errno = 0;
840
841 if ( !stream )
842  return -1;
843
844 roar_vio_set_fh(&(stream->vio), ROAR_STREAM(stream)->fh);
845
846 if ( ! stream->vio.read )
847  return -1;
848
849 while ( (r = roar_vio_read(&(stream->vio), buf, count)) > 0 ) {
850  len   += r;
851  buf   += r;
852  count -= r;
853  if ( count == 0 )
854   break;
855 }
856
857 if ( len == 0 && r == -1 )
858  return -1;
859
860 return len;
861}
862
863ssize_t stream_vio_s_write(struct roar_stream_server * stream, void *buf, size_t count) {
864 errno = 0;
865
866 if ( !stream )
867  return -1;
868
869 if ( roar_vio_get_fh(&(stream->vio)) == -1 && ROAR_STREAM(stream)->fh != -1 )
870  roar_vio_set_fh(&(stream->vio), ROAR_STREAM(stream)->fh);
871
872// ROAR_WARN("stream_vio_s_write(*): writing...");
873
874 return roar_vio_write(&(stream->vio), buf, count);
875}
876
877//ll
Note: See TracBrowser for help on using the repository browser.