source: roaraudio/roard/streams.c @ 4346:0dbee113ccd0

Last change on this file since 4346:0dbee113ccd0 was 4346:0dbee113ccd0, checked in by phi, 14 years ago

added ROAR_OE_BASICS_NEW/ROAR_OE_BASICS_DELETE for clients and streams

File size: 52.4 KB
Line 
1//streams.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#define _CHECK_SID_RET(id,ret) if ( (id) < 0 || (id) > ROAR_STREAMS_MAX || g_streams[(id)] == NULL ) return (ret)
29#define _CHECK_SID(id)         _CHECK_SID_RET((id), -1)
30
31int streams_thru_num     =  0;
32int streams_recsource_id = -1;
33
34static void _streams_change_state(struct roar_stream_server * s, const int new, const char * func) {
35 register int id  = ROAR_STREAM(s)->id;
36 register int old = s->state;
37
38 s->state = new;
39
40 if ( func == NULL ) {
41  func = "(unknown)";
42 }
43
44 ROAR_INFO("_streams_change_state[by %s](id=%i): stream state: %s->%s", ROAR_DBG_INFO_VERBOSE,
45            func,
46            ROAR_STREAM(s)->id,
47            roar_streamstate2str(old), roar_streamstate2str(new));
48
49 roar_notify_core_emit_simple(ROAR_OE_BASICS_CHANGE_STATE, -1, id, ROAR_OT_STREAM, old, new, NULL, 0);
50}
51
52int streams_init (void) {
53 int i;
54
55 for (i = 0; i < ROAR_STREAMS_MAX; i++)
56  g_streams[i] = NULL;
57
58 return 0;
59}
60
61int streams_free (void) {
62 int i;
63
64 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
65  if ( g_streams[i] != NULL ) {
66   streams_delete(i);
67  }
68 }
69
70 return 0;
71}
72
73
74int streams_new    (void) {
75 int i, j;
76 struct roar_stream        * n = NULL;
77 struct roar_stream_server * s = NULL;
78
79#ifdef ROAR_SUPPORT_LISTEN
80 if ( g_terminate && !g_no_listen ) // don't accept new streams in case of termination state
81  return -1;
82#else
83 if ( g_terminate )                 // don't accept new streams in case of termination state
84  return -1;
85#endif
86
87 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
88  if ( g_streams[i] == NULL ) {
89   s = ROAR_STREAM_SERVER(n = ROAR_STREAM(roar_mm_malloc(sizeof(struct roar_stream_server))));
90   if ( n == NULL ) {
91    ROAR_ERR("streams_new(void): can not allocate memory for new stream: %s", strerror(errno));
92    ROAR_DBG("streams_new(void) = -1");
93    return -1;
94   }
95
96   memset(s, 0, sizeof(struct roar_stream_server));
97
98   n->id         = i;
99   n->fh         = -1;
100   n->pos_rel_id = -1;
101/*
102   n->database   = NULL;
103   n->dataoff    = NULL;
104   n->datalen    = 0;
105   n->offset     = 0;
106*/
107   n->pos        = 0;
108
109   s->name            = NULL;
110
111   s->state           = ROAR_STREAMSTATE_INITING;
112
113   s->client          = -1;
114   s->socktype        = ROAR_SOCKET_TYPE_UNKNOWN;
115   s->buffer          = NULL;
116   s->need_extra      =  0;
117   s->output          = NULL;
118   s->is_new          =  1;
119   s->codecfilter     = -1;
120   s->pre_underruns   =  0;
121   s->post_underruns  =  0;
122   s->delay           =  0;
123   s->codec_orgi      = -1;
124   s->primary         =  0;
125   s->ready           =  0;
126   s->outputbuffer    = NULL;
127   s->prethru         = NULL;
128   s->mixer_stream    = -1;
129   s->role            = ROAR_ROLE_UNKNOWN;
130   s->parent_stream   = -1;
131
132   s->mixer.scale     = 65535;
133   s->mixer.rpg_mul   = 1;
134   s->mixer.rpg_div   = 1;
135   for (j = 0; j < ROAR_MAX_CHANNELS; j++)
136    s->mixer.mixer[j] = 65535;
137
138#ifdef ROAR_SUPPORT_META
139   for (j = 0; j < ROAR_META_MAX_PER_STREAM; j++) {
140    s->meta[j].type   = ROAR_META_TYPE_NONE;
141    s->meta[j].key[0] = 0;
142    s->meta[j].value  = NULL;
143   }
144#endif
145
146   roar_vio_init_calls(&(s->vio));
147   roar_vio_init_calls(&(s->jumbo));
148   s->viop      = &(s->vio);
149   s->driver_id = -1;
150   s->flags     =  ROAR_FLAG_NONE;
151
152   //roardsp_fchain_init(&(s->fc));
153
154   g_streams[i] = s;
155   counters_inc(streams, 1);
156   ROAR_INFO("streams_new(void): New stream %i created (state=initing)", ROAR_DBG_INFO_VERBOSE, i);
157   ROAR_DBG("streams_new(void): n->id=%i", n->id);
158   roar_notify_core_emit_snoargs(ROAR_OE_BASICS_NEW, -1, i, ROAR_OT_STREAM);
159   ROAR_DBG("streams_new(void) = %i", i);
160   return i;
161  }
162 }
163
164 return -1;
165}
166
167int streams_delete (int id) {
168 struct roar_stream_server * s;
169 int prim;
170 int no_vio_close = 0;
171 int i;
172 int client;
173
174 _CHECK_SID(id);
175
176 if ( (s = g_streams[id]) == NULL )
177  return 0;
178
179 ROAR_DBG("streams_delete(id=%i) = ?", id);
180 ROAR_DBG("streams_delete(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(s)->id);
181
182 // in case we are allready closing it...
183 if ( s->state == ROAR_STREAMSTATE_CLOSING )
184  return 0;
185
186 _streams_change_state(s, ROAR_STREAMSTATE_CLOSING, "streams_delete");
187 roar_notify_core_emit_snoargs(ROAR_OE_BASICS_DELETE, -1, id, ROAR_OT_STREAM);
188
189 counters_inc(streams, -1);
190
191 if ( streams_get_flag(id, ROAR_FLAG_RECSOURCE) == 1 )
192  streams_reset_flag(id, ROAR_FLAG_RECSOURCE);
193
194 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
195  if ( g_streams[i] != NULL && ROAR_STREAM(g_streams[i])->pos_rel_id == id ) {
196   switch (ROAR_STREAM(g_streams[i])->dir) {
197    case ROAR_DIR_THRU:
198    case ROAR_DIR_RAW_IN:
199      if ( i != id )
200       streams_delete(i);
201     break;
202    default:
203      if ( streams_get_flag(i, ROAR_FLAG_VIRTUAL) == 1 ) {
204       if ( i != id ) {
205        ROAR_DBG("streams_delete(id=%i): Deleting virtual child stream %i", id, i);
206        streams_delete(i);
207       }
208      } else {
209       ROAR_STREAM(g_streams[i])->pos_rel_id = -1;
210      }
211   }
212  }
213 }
214
215 if ( ROAR_STREAM(s)->dir == ROAR_DIR_THRU )
216  streams_thru_num--;
217
218 if ( streams_get_flag(id, ROAR_FLAG_VIRTUAL) == 1 ) {
219  // we un-group the stream here to avoid a client deleting the parent deleting the client deleting ...
220  i      = ROAR_STREAM(s)->pos_rel_id;
221  if ( i != -1 ) {
222   ROAR_STREAM(s)->pos_rel_id = -1;
223   client = streams_get_client(id);
224   streams_set_client(id, -1);
225   ROAR_DBG("streams_delete(id=%i): Stream has flag virtual, notifying parent stream %i", id, i);
226   streams_ctl(i, ROAR_CODECFILTER_CTL_VIRTUAL_DELETE|ROAR_STREAM_CTL_TYPE_INT, &id);
227   ROAR_DBG("streams_delete(id=%i): Notify send to stream %i", id, i);
228   streams_set_client(id, client);
229   ROAR_STREAM(s)->pos_rel_id = i;
230  }
231 }
232
233#ifdef ROAR_SUPPORT_META
234 // delete meta data form other meta streams if needed
235 if ( streams_get_flag(id, ROAR_FLAG_META) == 1 ) {
236  ROAR_DBG("streams_delete(id=%i): deleting meta stream!", id);
237  stream_meta_clear(id);
238  stream_meta_finalize(id);
239 }
240#endif
241
242 if ( s->codecfilter != -1 ) {
243  codecfilter_close(s->codecfilter_inst, s->codecfilter);
244  s->codecfilter_inst = NULL;
245  s->codecfilter = -1;
246 }
247
248 if ( s->driver_id != -1 ) {
249  driver_closevio(&(s->vio), s->driver_id);
250  roar_vio_init_calls(&(s->vio));
251  s->driver_id = -1;
252  no_vio_close =  1;
253 }
254
255 //roardsp_fchain_uninit(&(s->fc));
256
257 if ( s->client != -1 ) {
258  ROAR_DBG("streams_delete(id=%i): Stream is owned by client %i", id, g_streams[id]->client);
259  client_stream_delete(s->client, id);
260 }
261
262 stream_outputbuffer_destroy(id);
263 stream_prethru_destroy(id);
264
265 if ( s->buffer != NULL )
266  roar_buffer_free(s->buffer);
267
268 if ( s->output != NULL )
269  free(s->output);
270
271/*
272 if ( ROAR_STREAM(s)->fh != -1 )
273  close(ROAR_STREAM(s)->fh);
274*/
275
276 if ( !no_vio_close )
277  roar_vio_close(s->viop);
278
279 prim = s->primary;
280
281 if ( s->name != NULL )
282  free(s->name);
283
284 roar_mm_free(s);
285
286 g_streams[id] = NULL;
287
288 if ( prim && alive ) {
289  alive = 0;
290  clean_quit();
291 }
292
293 ROAR_INFO("streams_delete(id=%i): stream deleted", ROAR_DBG_INFO_VERBOSE, id);
294 ROAR_DBG("streams_delete(id=%i) = 0", id);
295 return 0;
296}
297
298int streams_set_client (int id, int client) {
299
300 _CHECK_SID(id);
301
302 ROAR_DBG("streams_set_client(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(g_streams[id])->id);
303 g_streams[id]->client = client;
304
305 return 0;
306}
307
308int streams_get_client (int id) {
309 _CHECK_SID(id);
310
311 return g_streams[id]->client;
312}
313
314int streams_set_dir    (int id, int dir, int defaults) {
315 struct roar_stream_server * ss;
316
317 _CHECK_SID(id);
318
319 if ( (ss = g_streams[id]) == NULL )
320  return -1;
321
322 ROAR_STREAM(ss)->dir = dir;
323
324 if ( dir == ROAR_DIR_THRU )
325  streams_thru_num++;
326
327 if ( defaults ) {
328  if ( dir <= 0 || dir >= ROAR_DIR_DIRIDS )
329   return -1;
330
331  ROAR_DBG("streams_set_dir(*): g_config->streams[dir=%i].flags = 0x%.4x", dir, g_config->streams[dir].flags);
332
333  if ( streams_set_flag(id, g_config->streams[dir].flags) == -1 ) {
334   ROAR_DBG("streams_set_dir(*) = -1 // can not set stream flags");
335   return -1;
336  }
337
338   ss->mixer.scale   = g_config->streams[dir].mixer.scale;
339   ss->mixer.rpg_mul = g_config->streams[dir].mixer.rpg_mul;
340   ss->mixer.rpg_div = g_config->streams[dir].mixer.rpg_div;
341 }
342
343 if ( dir != ROAR_DIR_MIXING ) {
344  switch (streams_get_subsys(id)) {
345   case ROAR_SUBSYS_WAVEFORM:
346     streams_set_mixer_stream(id, g_waveform_mixer.stream);
347     roardsp_chanlist_init(ss->chanmap.in,  ROAR_STREAM(ss)->info.channels, ROARDSP_CHANLIST_MAP_ROARAUDIO);
348    break;
349#ifndef ROAR_WITHOUT_DCOMP_MIDI
350   case ROAR_SUBSYS_MIDI:
351     roardsp_chanlist_init(ss->chanmap.in,  ROAR_STREAM(ss)->info.channels, ROARDSP_CHANLIST_MAP_MIDI);
352     streams_set_mixer_stream(id, g_midi_mixer.stream);
353    break;
354#endif
355#ifndef ROAR_WITHOUT_DCOMP_LIGHT
356   case ROAR_SUBSYS_LIGHT:
357     streams_set_mixer_stream(id, g_light_mixer.stream);
358    break;
359#endif
360  }
361
362  memcpy(ss->chanmap.out, ss->chanmap.in, sizeof(ss->chanmap.out));
363  streams_set_map(id, NULL, 0);
364 } else {
365  streams_set_mixer_stream(id, id);
366 }
367
368 ROAR_DBG("streams_set_dir(*) = 0");
369 return 0;
370}
371
372int streams_get_dir    (int id) {
373 struct roar_stream_server * ss;
374
375 _CHECK_SID(id);
376
377 if ( (ss = g_streams[id]) == NULL )
378  return -1;
379
380 return ROAR_STREAM(ss)->dir;
381}
382
383int streams_set_mixer_stream(int id, int mixer) {
384 struct roar_stream_server * ss;
385
386 _CHECK_SID(id);
387
388 if ( (ss = g_streams[id]) == NULL )
389  return -1;
390
391 ss->mixer_stream = mixer;
392
393 return 0;
394}
395
396int streams_get_mixer_stream(int id, int mixer) {
397 struct roar_stream_server * ss;
398
399 _CHECK_SID(id);
400
401 if ( (ss = g_streams[id]) == NULL )
402  return -1;
403
404 return ss->mixer_stream;
405}
406
407int streams_set_role   (int id, int role) {
408 struct roar_stream_server * ss;
409
410 _CHECK_SID(id);
411
412 if ( (ss = g_streams[id]) == NULL )
413  return -1;
414
415 ss->role = role;
416
417 return 0;
418}
419
420int streams_get_subsys (int id) {
421 struct roar_stream_server * ss;
422
423 _CHECK_SID(id);
424
425 if ( (ss = g_streams[id]) == NULL )
426  return -1;
427
428 switch (ROAR_STREAM(ss)->dir) {
429  case ROAR_DIR_PLAY:
430  case ROAR_DIR_RECORD:
431  case ROAR_DIR_MONITOR:
432  case ROAR_DIR_FILTER:
433  case ROAR_DIR_OUTPUT:
434  case ROAR_DIR_BIDIR:
435    return ROAR_SUBSYS_WAVEFORM;
436   break;
437  case ROAR_DIR_MIDI_IN:
438  case ROAR_DIR_MIDI_OUT:
439    return ROAR_SUBSYS_MIDI;
440   break;
441  case ROAR_DIR_LIGHT_IN:
442  case ROAR_DIR_LIGHT_OUT:
443    return ROAR_SUBSYS_LIGHT;
444   break;
445  case ROAR_DIR_RAW_IN:
446  case ROAR_DIR_RAW_OUT:
447    return ROAR_SUBSYS_RAW;
448   break;
449  case ROAR_DIR_COMPLEX_IN:
450  case ROAR_DIR_COMPLEX_OUT:
451    return ROAR_SUBSYS_COMPLEX;
452   break;
453  case ROAR_DIR_THRU:
454    return streams_get_subsys(ROAR_STREAM(ss)->pos_rel_id);
455   break;
456 }
457
458 return -1;
459}
460
461int streams_get_ssdir  (int id) {
462 struct roar_stream_server * ss;
463
464 _CHECK_SID(id);
465
466 if ( (ss = g_streams[id]) == NULL )
467  return -1;
468
469 switch (ROAR_STREAM(ss)->dir) {
470  case ROAR_DIR_PLAY:
471  case ROAR_DIR_MIDI_IN:
472  case ROAR_DIR_LIGHT_IN:
473  case ROAR_DIR_RAW_IN:
474  case ROAR_DIR_COMPLEX_IN:
475    return STREAM_DIR_IN;
476   break;
477  case ROAR_DIR_RECORD:
478  case ROAR_DIR_MONITOR:
479  case ROAR_DIR_OUTPUT:
480  case ROAR_DIR_MIDI_OUT:
481  case ROAR_DIR_LIGHT_OUT:
482  case ROAR_DIR_RAW_OUT:
483  case ROAR_DIR_COMPLEX_OUT:
484    return STREAM_DIR_OUT;
485   break;
486  case ROAR_DIR_MIXING:
487    return STREAM_DIR_NONE;
488   break;
489  case ROAR_DIR_FILTER:
490  case ROAR_DIR_BIDIR:
491    return STREAM_DIR_BIDIR;
492   break;
493  case ROAR_DIR_THRU:
494    return streams_get_ssdir(ROAR_STREAM(ss)->pos_rel_id);
495   break;
496 }
497
498 return -1;
499}
500
501#define _err() streams_delete(id); return -1;
502int streams_new_virtual (int parent, struct roar_stream_server ** stream) {
503 struct roar_stream_server * parent_ss, * ss;
504 struct roar_stream        * parent_s , *  s;
505 int id = -1;
506 int client, dir;
507
508 if ( streams_get(parent, &parent_ss) == -1 )
509  return -1;
510
511 if ( (client = streams_get_client(parent)) == -1 )
512  return -1;
513
514 if ( (dir = streams_get_dir(parent)) == -1 )
515  return -1;
516
517 if ( (id = streams_new()) == -1 ) {
518  return -1;
519 }
520
521 if ( client_stream_add(client, id) == -1 ) {
522  _err();
523 }
524
525 if ( streams_get(id, &ss) == -1 ) {
526  _err();
527 }
528
529 if ( streams_set_dir(id, dir, 1) == -1 ) {
530  _err();
531 }
532
533 s        = ROAR_STREAM(       ss);
534 parent_s = ROAR_STREAM(parent_ss);
535
536 s->pos_rel_id = parent;
537
538 if ( streams_set_rawflag(id, ROAR_FLAG_VIRTUAL) == -1 ) {
539  _err();
540 }
541
542 if ( stream != NULL )
543  *stream = ss;
544
545 return id;
546}
547#undef _err
548
549int streams_set_fh     (int id, int fh) {
550 struct roar_stream_server * ss;
551 struct roar_stream        * s;
552 int dir;
553 int nonblock = 1;
554
555 _CHECK_SID(id);
556
557 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
558  return -1;
559
560 if ( ss->ready ) {
561  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = -1 // try to set fh for stream which is already ready", id, fh);
562  return -1;
563 }
564
565 dir = ROAR_STREAM(ss)->dir;
566
567 ROAR_DBG("streams_set_fh(id=%i, fh=%i): g_streams[id]->id=%i", id, fh, s->id);
568
569 s->fh = fh;
570
571 ROAR_DBG("streams_set_fh(id=%i, fh=%i): driverID=%i", id, fh, ss->driver_id);
572
573 if ( ss->driver_id == -1 && fh != -2 ) {
574#ifndef ROAR_TARGET_WIN32
575  roar_vio_set_fh(&(ss->vio), fh);
576#else
577  roar_vio_open_fh_socket(&(ss->vio), fh);
578#endif
579 }
580
581 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
582
583 switch (dir) {
584  case ROAR_DIR_THRU:
585  case ROAR_DIR_RAW_IN:
586  case ROAR_DIR_RAW_OUT:
587   break;
588  default:
589    if ( codecfilter_open(&(ss->codecfilter_inst), &(ss->codecfilter), NULL,
590                     s->info.codec, ss) == -1 ) {
591     streams_delete(id); // TODO: FIXME: is this correct? shoudn't we return -1 in any case here?
592     return -1;
593    }
594   break;
595 }
596
597 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
598
599 if ( fh == -2 ) {
600  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
601  if ( roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_GET_READ_FH, &fh) == -1 ) {
602   fh = -2;
603  } else {
604   ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
605   if ( fh < 0 ) {
606    fh = -2;
607   } else {
608    s->fh = fh;
609   }
610  }
611 }
612
613 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
614
615 if ( fh == -1 || fh == -2 ) { // yes, this is valid, indecats full vio!
616  ss->ready = 1;
617  //ROAR_INFO("streams_set_fh(id=%i, fh=%i): stream state: %s->new", ROAR_DBG_INFO_VERBOSE, id, fh, roar_streamstate2str(ss->state));
618  _streams_change_state(ss, ROAR_STREAMSTATE_NEW, "streams_set_fh");
619  return 0;
620 }
621
622 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
623
624// roar_socket_recvbuf(fh, ROAR_OUTPUT_CALC_OUTBUFSIZE( &(ROAR_STREAM(g_streams[id])->info) )); // set recv buffer to minimum
625
626 switch (dir) {
627  case ROAR_DIR_MONITOR:
628  case ROAR_DIR_RECORD:
629  case ROAR_DIR_OUTPUT:
630  case ROAR_DIR_MIDI_OUT:
631  case ROAR_DIR_LIGHT_OUT:
632  case ROAR_DIR_RAW_OUT:
633    ROAR_SHUTDOWN(fh, SHUT_RD);
634   break;
635 }
636
637 if ( dir >= ROAR_DIR_DIRIDS )
638  return -1;
639
640 if ( g_config->streams[dir].flags & ROAR_FLAG_SYNC ) {
641  switch (dir) {
642   case ROAR_DIR_BRIDGE:
643   case ROAR_DIR_MIDI_OUT:
644    break;
645   default:
646     nonblock = 0;
647    break;
648  }
649 }
650
651
652 if ( !nonblock ) {
653  ss->ready = 1;
654  //ROAR_INFO("streams_set_fh(id=%i, fh=%i): stream state: %s->new", ROAR_DBG_INFO_VERBOSE, id, fh, roar_streamstate2str(ss->state));
655  _streams_change_state(ss, ROAR_STREAMSTATE_NEW, "streams_set_fh");
656
657  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = 0", id, fh);
658  return 0;
659 } else {
660#ifndef ROAR_TARGET_WIN32
661  if ( roar_socket_nonblock(fh, ROAR_SOCKET_NONBLOCK) == -1 )
662   return -1;
663#endif
664
665  ss->ready = 1;
666  //ROAR_INFO("streams_set_fh(id=%i, fh=%i): stream state: %s->new", ROAR_DBG_INFO_VERBOSE, id, fh, roar_streamstate2str(ss->state));
667  _streams_change_state(ss, ROAR_STREAMSTATE_NEW, "streams_set_fh");
668
669  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = 0", id, fh);
670  return 0;
671 }
672}
673
674int streams_get_fh     (int id) {
675 _CHECK_SID(id);
676
677 return ROAR_STREAM(g_streams[id])->fh;
678}
679
680int streams_set_null_io(int id) {
681 struct roar_stream_server * ss;
682 struct roar_stream        * s;
683
684 _CHECK_SID(id);
685
686 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
687  return -1;
688
689 s->fh = -1;
690
691 return 0;
692}
693
694int streams_get    (int id, struct roar_stream_server ** stream) {
695 _CHECK_SID(id);
696
697 *stream = g_streams[id];
698
699 return 0;
700}
701
702int streams_set_socktype (int id, int socktype) {
703 _CHECK_SID(id);
704
705 g_streams[id]->socktype = socktype;
706
707 return 0;
708}
709
710int streams_get_socktype (int id) {
711 _CHECK_SID(id);
712
713 return g_streams[id]->socktype;
714}
715
716int streams_is_ready     (int id) {
717 _CHECK_SID(id);
718
719 return g_streams[id]->ready;
720}
721
722int streams_set_primary (int id, int prim) {
723 _CHECK_SID(id);
724
725 g_streams[id]->primary = prim;
726
727 return 0;
728}
729
730int streams_mark_primary (int id) {
731 return streams_set_primary(id, 1);
732}
733
734int streams_set_sync     (int id, int sync) {
735 int fh = streams_get_fh(id);
736
737 _CHECK_SID(id);
738
739 if ( fh != -1 ) {
740  if ( roar_socket_nonblock(fh, sync ? ROAR_SOCKET_BLOCK : ROAR_SOCKET_NONBLOCK) == -1 )
741   return -1;
742
743#ifdef ROAR_FDATASYNC
744  ROAR_FDATASYNC(fh);
745#endif
746
747  return 0;
748 } else {
749  return roar_vio_nonblock(&(g_streams[id]->vio), sync);
750 }
751}
752
753int streams_set_mmap (int id, int reset) {
754 int use = !reset;
755
756 _CHECK_SID(id);
757
758 return roar_vio_ctl(&(g_streams[id]->vio), ROAR_VIO_CTL_SET_UMMAP, &use);
759}
760
761int streams_set_flag     (int id, int flag) {
762 int parent;
763
764 _CHECK_SID(id);
765
766 if ( flag & ROAR_FLAG_IMMUTABLE )
767  flag |= ROAR_FLAG_PRIMARY;
768
769 if ( flag & ROAR_FLAG_MMAP )
770  if ( streams_set_mmap(id, 0) == -1 )
771   flag -= ROAR_FLAG_MMAP;
772
773 if ( flag & ROAR_FLAG_PRIMARY ) {
774  streams_set_primary(id, 1);
775  flag -= ROAR_FLAG_PRIMARY;
776 }
777
778 if ( flag & ROAR_FLAG_VIRTUAL ) {
779  if ( (parent = ROAR_STREAM(g_streams[id])->pos_rel_id) == -1 )
780   return -1;
781
782  if ( streams_ctl(parent, ROAR_CODECFILTER_CTL_VIRTUAL_NEW|ROAR_STREAM_CTL_TYPE_INT, &id) == -1 ) {
783//   flag -= ROAR_FLAG_VIRTUAL;
784   return -1;
785  }
786
787  if ( client_stream_move(streams_get_client(parent), id) == -1 ) {
788   return -1;
789  }
790 }
791
792 if ( flag & ROAR_FLAG_SYNC ) {
793  switch (ROAR_STREAM(g_streams[id])->dir) {
794   // for this stream types the flag is used in the subsystem:
795   case ROAR_DIR_BRIDGE:
796   case ROAR_DIR_MIDI_OUT:
797    break;
798
799   // normal behavor (vio blocking):
800   default:
801     // the fh is updated as soon as the fh get ready in case the default ask to set sync
802     if ( !g_streams[id]->ready && !(g_config->streams[ROAR_STREAM(g_streams[id])->dir].flags & ROAR_FLAG_SYNC) ) {
803      if ( streams_set_sync(id, 1) == -1 )
804       flag -= ROAR_FLAG_SYNC;
805     }
806  }
807 }
808
809 if ( flag & ROAR_FLAG_HWMIXER ) { // currently not supported -> ignored
810  g_streams[id]->flags |= flag;
811  if ( streams_set_mixer(id) == -1 ) {
812   g_streams[id]->flags -= flag;
813   return -1;
814  }
815 }
816
817 if ( flag & ROAR_FLAG_RECSOURCE ) {
818  if ( streams_recsource_id != -1 ) {
819   if ( streams_reset_flag(streams_recsource_id, ROAR_FLAG_RECSOURCE) == -1 )
820    return -1;
821  }
822
823  streams_recsource_id = id;
824 }
825
826 g_streams[id]->flags |= flag;
827
828#ifdef ROAR_SUPPORT_META
829 if ( flag & ROAR_FLAG_META )
830  stream_meta_finalize(id);
831#endif
832
833 return 0;
834}
835
836int streams_set_rawflag  (int id, int flag) {
837 _CHECK_SID(id);
838
839 g_streams[id]->flags |= flag;
840
841 return 0;
842}
843
844int streams_reset_flag   (int id, int flag) {
845 _CHECK_SID(id);
846
847 if ( g_streams[id]->flags & ROAR_FLAG_IMMUTABLE ) {
848  flag |= ROAR_FLAG_PRIMARY;
849  flag -= ROAR_FLAG_PRIMARY;
850 }
851
852 if ( flag & ROAR_FLAG_RECSOURCE )
853  if ( streams_recsource_id == id )
854   streams_recsource_id = -1;
855
856 if ( flag & ROAR_FLAG_MMAP )
857  if ( streams_set_mmap(id, 1) == -1 )
858   flag -= ROAR_FLAG_MMAP;
859
860 if ( flag & ROAR_FLAG_PRIMARY ) {
861  streams_set_primary(id, 0);
862  flag -= ROAR_FLAG_PRIMARY;
863 }
864
865 if ( flag & ROAR_FLAG_SYNC ) {
866  // we refuse to reset the flag on FILTER streams
867  if ( streams_get_dir(id) == ROAR_DIR_FILTER ) {
868//   flags -= ROAR_FLAG_SYNC;
869   return -1;
870  } else {
871   streams_set_sync(id, 0);
872  }
873 }
874
875 g_streams[id]->flags |= flag;
876 g_streams[id]->flags -= flag;
877
878 return 0;
879}
880
881int streams_get_flag     (int id, int flag) {
882 _CHECK_SID(id);
883
884 return g_streams[id]->flags & flag ? 1 : 0;
885}
886
887int streams_set_name     (int id, char * name) {
888 char * str;
889
890 _CHECK_SID(id);
891
892 if ( (str = strdup(name)) == NULL )
893  return -1;
894
895 if ( g_streams[id]->name != NULL )
896  free(g_streams[id]->name);
897
898 g_streams[id]->name = str;
899
900 return 0;
901}
902
903char * streams_get_name  (int id) {
904 _CHECK_SID_RET(id, NULL);
905
906 return g_streams[id]->name;
907}
908
909
910int streams_calc_delay    (int id) {
911 struct roar_stream_server * ss;
912 struct roar_stream        * s;
913 register uint_least32_t d = 0;
914 uint_least32_t t[1];
915 uint64_t       tmp;
916
917 _CHECK_SID(id);
918
919 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
920  return -1;
921
922 // mixer store there value in ss->delay directly
923 if ( s->dir == ROAR_DIR_MIXING )
924  return 0;
925
926#if 0
927 // this only confuses the user...
928 if ( ss->mixer_stream != id ) {
929  if ( streams_calc_delay(ss->mixer_stream) != -1 ) {
930   d += g_streams[ss->mixer_stream]->delay; // in case we can calc the delay
931                                            // the stream must exist, so no check here
932  }
933 }
934#endif
935
936 if ( ss->codecfilter != -1 ) {
937  if ( codecfilter_delay(ss->codecfilter_inst, ss->codecfilter, t) != -1 )
938   d += *t;
939 }
940
941 if ( ss->vio.ctl != NULL ) {
942  if ( roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_GET_DELAY, t) != -1 ) { // *t is in byte
943   ROAR_DBG("streams_calc_delay(id=%i): VIO delay in byte: %i", id, *t);
944   tmp = *t;
945   tmp *= 1000000; // musec per sec
946   tmp /= s->info.rate * s->info.channels * (s->info.bits/8);
947   ROAR_DBG("streams_calc_delay(id=%i): VIO delay in musec: %llu", id, tmp);
948
949   d += tmp;
950  }
951 }
952
953 ROAR_DBG("streams_calc_delay(id=%i): delay in musec: %i", id, d);
954
955 ss->delay = d;
956
957 return 0;
958}
959
960int streams_set_mixer    (int id) {
961 struct roar_stream_server * ss;
962 struct roar_stream_server * pmss;
963 int i;
964 int subsys;
965
966 _CHECK_SID(id);
967
968 if ( (ss = g_streams[id]) == NULL )
969  return -1;
970
971 if ( streams_get_flag(id, ROAR_FLAG_PASSMIXER) == 1 ) {
972  if ( (subsys = streams_get_subsys(id)) == -1 )
973   return -1;
974
975  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
976   if ( (pmss = g_streams[i]) != NULL ) {
977    if ( streams_get_flag(i, ROAR_FLAG_PASSMIXER) == 1 ) {
978     if ( streams_get_subsys(i) == subsys ) {
979      if ( &(pmss->mixer) != &(ss->mixer) ) {
980       memcpy(&(pmss->mixer), &(ss->mixer), sizeof(struct roar_mixer_settings));
981      }
982
983      // update hwmixers and the like but do not set mixer value recrusivly.
984      streams_reset_flag(i, ROAR_FLAG_PASSMIXER);
985      streams_set_mixer(i);
986      streams_set_flag(i, ROAR_FLAG_PASSMIXER);
987     }
988    }
989   }
990  }
991 }
992
993 if ( !streams_get_flag(id, ROAR_FLAG_HWMIXER) )
994  return 0;
995
996 if ( ss->driver_id == -1 )
997  return 0;
998
999 return driver_set_volume(id, &(ss->mixer));
1000}
1001
1002int streams_set_map      (int id, char * map, size_t len) {
1003 struct roar_stream_server * ss;
1004 int ssdir;
1005
1006 _CHECK_SID(id);
1007
1008 if ( (ss = g_streams[id]) == NULL )
1009  return -1;
1010
1011 if ( map != NULL ) {
1012  if ( ROAR_STREAM(ss)->info.channels != len )
1013   return -1;
1014 }
1015
1016 ssdir = streams_get_ssdir(id);
1017
1018 switch (ssdir) {
1019  case STREAM_DIR_IN:
1020  case STREAM_DIR_NONE:
1021    memset(ss->chanmap.in, 0, sizeof(ss->chanmap.in));
1022
1023    if ( map != NULL )
1024     memcpy(ss->chanmap.in, map, len);
1025
1026    roardsp_chanmap_calc(&(ss->chanmap), ROARDSP_CHANMAP_MAP, 0);
1027   break;
1028  case STREAM_DIR_OUT:
1029    memset(ss->chanmap.out, 0, sizeof(ss->chanmap.out));
1030
1031    if ( map != NULL )
1032     memcpy(ss->chanmap.out, map, len);
1033
1034    roardsp_chanmap_calc(&(ss->chanmap), ROARDSP_CHANMAP_MAP, 0);
1035   break;
1036  default:
1037    return -1;
1038 }
1039
1040 return 0;
1041}
1042
1043int streams_ltm_ctl      (int id, int mt, int window, int cmd) {
1044 struct roar_stream_server * ss;
1045 struct roar_stream_ltm *    ltm;
1046 int i;
1047
1048 _CHECK_SID(id);
1049
1050 // currently we only support the WORKBLOCK window
1051 if ( window != ROAR_LTM_WIN_WORKBLOCK )
1052  return -1;
1053
1054 // currently we only support ROAR_LTM_MT_RMS
1055 if ( (mt | ROAR_LTM_MT_RMS) - ROAR_LTM_MT_RMS )
1056  return -1;
1057
1058 if ( (ss = g_streams[id]) == NULL )
1059  return -1;
1060
1061 switch (cmd) {
1062  case ROAR_LTM_SST_NOOP:
1063    return 0;
1064   break;
1065  case ROAR_LTM_SST_REGISTER:
1066    // test if the window is already registered:
1067    for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1068     ltm = &(ss->ltm[i]);
1069     if ( ltm->refc && ltm->window == window ) {
1070      ltm->refc++;
1071      ltm->mt |= mt;
1072      return 0;
1073     }
1074    }
1075
1076    // register
1077    for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1078     ltm = &(ss->ltm[i]);
1079     if ( ltm->refc == 0 ) {
1080      memset(ltm, 0, sizeof(struct roar_stream_ltm));
1081      ltm->refc = 1;
1082      ltm->window = window;
1083      ltm->parent_window = -1;
1084      ltm->mt = mt;
1085      ltm->channels = ROAR_STREAM(ss)->info.channels;
1086      if ( (ltm->cur = roar_mm_malloc(ltm->channels*sizeof(struct roar_ltm_vals))) == NULL ) {
1087       ltm->refc = 0; // reset
1088       return -1;
1089      }
1090      memset(ltm->cur, 0, ltm->channels*sizeof(struct roar_ltm_vals));
1091      return 0;
1092     }
1093    }
1094    return -1;
1095   break;
1096  case ROAR_LTM_SST_UNREGISTER:
1097    for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1098     ltm = &(ss->ltm[i]);
1099     if ( ltm->refc && ltm->window == window ) {
1100      ltm->refc--;
1101      if ( ! ltm->refc ) {
1102       roar_mm_free(ltm->cur);
1103       return 0;
1104      }
1105     }
1106    }
1107    return -1;
1108   break;
1109  default:
1110    return -1;
1111   break;
1112 }
1113}
1114
1115int streams_ltm_calc     (int id, struct roar_audio_info * info, void * data, size_t len) {
1116 struct roar_stream_server * ss;
1117 struct roar_stream_ltm *    ltm = NULL;
1118 int64_t rmsbuf_real[8];
1119 int64_t * rmsbuf = rmsbuf_real;
1120 size_t samples = 0;
1121 int i;
1122
1123 _CHECK_SID(id);
1124
1125 if ( data == NULL || info == NULL )
1126  return -1;
1127
1128 if ( info->codec != ROAR_CODEC_DEFAULT )
1129  return -1;
1130
1131 if ( (ss = g_streams[id]) == NULL )
1132  return -1;
1133
1134 for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1135  if ( ss->ltm[i].refc && ss->ltm[i].window == ROAR_LTM_WIN_WORKBLOCK ) {
1136   ltm = &(ss->ltm[i]);
1137   break;
1138  }
1139 }
1140
1141 if ( ltm == NULL )
1142  return -1;
1143
1144 // TODO: support change of number of channels
1145 if ( ltm->channels != info->channels )
1146  return -1;
1147
1148 if ( len == 0 ) {
1149  memset(ltm->cur, 0, ltm->channels * sizeof(struct roar_ltm_vals));
1150  return 0;
1151 }
1152
1153 // TODO: support more channels then rmsbuf_real has space for
1154 if ( ltm->channels > (sizeof(rmsbuf_real)/sizeof(*rmsbuf_real)) ) {
1155  return -1;
1156 }
1157
1158 samples = len / info->bits;
1159
1160 if ( ltm->mt & ROAR_LTM_MT_RMS ) {
1161  if ( roar_rms2_1_b_n(data, samples, rmsbuf, ltm->channels, info->bits) == -1 )
1162   return -1;
1163
1164  for (i = 0; i < ltm->channels; i++) {
1165   ltm->cur[i].rms = rmsbuf[i] << (64 - info->bits*2);
1166  }
1167
1168  ROAR_DBG("streams_ltm_calc(id=%i,...): rmsbuf[0]=%lli", id, (long long int)rmsbuf[0]);
1169 }
1170
1171 return 0;
1172}
1173
1174struct roar_stream_ltm * streams_ltm_get(int id, int mt, int window) {
1175 struct roar_stream_server * ss;
1176 struct roar_stream_ltm *    ltm = NULL;
1177 int i;
1178
1179 _CHECK_SID_RET(id, NULL);
1180
1181 if ( (ss = g_streams[id]) == NULL )
1182  return NULL;
1183
1184 for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1185  if ( ss->ltm[i].refc && ss->ltm[i].window == window ) {
1186   ltm = &(ss->ltm[i]);
1187   break;
1188  }
1189 }
1190
1191 if ( ltm == NULL )
1192  return NULL;
1193
1194 if ( (ltm->mt & mt) != mt )
1195  return NULL;
1196
1197 return ltm;
1198}
1199
1200
1201int streams_ctl          (int id, int_least32_t cmd, void * data) {
1202 struct roar_stream_server * ss;
1203 int_least32_t comp;
1204
1205 _CHECK_SID(id);
1206
1207 if ( (ss = g_streams[id]) == NULL )
1208  return -1;
1209
1210 comp = cmd & ROAR_STREAM_CTL_COMPMASK;
1211
1212 cmd &= ~comp;
1213
1214 ROAR_DBG("streams_ctl(id=%i, cmd=?, data=%p): comp=0x%.8x, cmd=0x%.4x", id, data, comp, cmd);
1215
1216 switch (comp) {
1217  case ROAR_STREAM_CTL_COMP_BASE:
1218   break;
1219  case ROAR_STREAM_CTL_COMP_CF:
1220    return codecfilter_ctl(ss->codecfilter_inst, ss->codecfilter, cmd, data);
1221   break;
1222  case ROAR_STREAM_CTL_COMP_DRV:
1223   break;
1224  default:
1225   return -1;
1226 }
1227
1228 return -1;
1229}
1230
1231int streams_get_outputbuffer  (int id, void ** buffer, size_t size) {
1232 _CHECK_SID(id);
1233
1234 // output buffer size does never change.
1235 if ( g_streams[id]->output != NULL ) {
1236  *buffer = g_streams[id]->output;
1237  return 0;
1238 }
1239
1240 if ( (g_streams[id]->output = malloc(size)) == NULL ) {
1241  ROAR_ERR("streams_get_outputbuffer(*): Can not alloc: %s", strerror(errno));
1242  return -1;
1243 }
1244
1245 *buffer = g_streams[id]->output;
1246
1247 return 0;
1248}
1249
1250int streams_fill_mixbuffer2 (int id, struct roar_audio_info * info) {
1251 size_t   outlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(info);
1252 void   * outdata;
1253 size_t   inlen;
1254 size_t   inlen_got;
1255 void   * indata = NULL;
1256 size_t   buflen;
1257 void   * bufdata = NULL;
1258 struct roar_buffer * bufbuf = NULL;
1259 int      is_the_same = 0;
1260 struct roar_audio_info    * stream_info;
1261 struct roar_stream        * s;
1262 struct roar_stream_server * ss;
1263
1264 _CHECK_SID(id);
1265
1266 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
1267  return -1;
1268
1269 // set up stream_info
1270 stream_info = &(s->info);
1271
1272 // calc todo_in
1273 inlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(stream_info);
1274
1275 buflen = ROAR_OUTPUT_CALC_OUTBUFSIZE_MAX(info, stream_info);
1276
1277 ROAR_DBG("streams_fill_mixbuffer2(id=%i, info=%p{...}): inlen=%lu, buflen=%lu", id, info, (unsigned long)inlen, (unsigned long)buflen);
1278
1279 if ( inlen == 0 ) {
1280  ROAR_WARN("streams_fill_mixbuffer2(id=%i, info=%p{...}): inlen == 0, this should not happen!", id, info);
1281  return -1;
1282 }
1283
1284 if ( streams_get_outputbuffer(id, &outdata, outlen) == -1 ) {
1285  return -1;
1286 }
1287
1288 if ( outdata == NULL ) {
1289  return -1;
1290 }
1291
1292 ROAR_DBG("streams_fill_mixbuffer2(*): outdata=%p, len=%i->%i (in->out)", outdata, inlen, outlen);
1293
1294 is_the_same = stream_info->rate     == info->rate     && stream_info->bits  == info->bits &&
1295               stream_info->channels == info->channels && stream_info->codec == info->codec;
1296
1297 ROAR_DBG("streams_fill_mixbuffer2(*): is_the_same=%i", is_the_same);
1298
1299 if ( !is_the_same && buflen > outlen ) {
1300/*
1301  // this is not supported at the moment
1302  memset(outdata, 0, outlen);
1303  return -1;
1304*/
1305
1306  if ( roar_buffer_new(&bufbuf, buflen) == -1 )
1307   return -1;
1308
1309  if ( roar_buffer_get_data(bufbuf, &bufdata) == -1 )
1310   return -1;
1311  indata  = bufdata;
1312 } else {
1313  indata  = outdata;
1314  bufdata = outdata;
1315 }
1316
1317 inlen_got = inlen;
1318
1319 ROAR_DBG("streams_fill_mixbuffer2(id=%i, info=...): inlen_got=%u", id, inlen_got);
1320
1321 if ( stream_shift_out_buffer(id, indata, &inlen_got) == -1 ) {
1322  if ( ss->is_new ) {
1323   ss->pre_underruns++;
1324  } else {
1325   ROAR_WARN("streams_fill_mixbuffer2(id=%i, info=...): underrun in stream", id);
1326   ss->post_underruns++;
1327  }
1328  memset(outdata, 0, outlen);
1329  return 0;
1330 }
1331
1332 ROAR_DBG("streams_fill_mixbuffer2(id=%i, info=...): inlen_got=%u", id, inlen_got);
1333
1334 if ( ss->is_new ) {
1335  //ROAR_INFO("streams_fill_mixbuffer2(id=%i, info=...): stream state: new->old", ROAR_DBG_INFO_VERBOSE, id);
1336  _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_fill_mixbuffer2");
1337 }
1338
1339 ss->is_new = 0;
1340
1341 // check channel map:
1342#if 0
1343 if ( roardsp_chanmap_mappcm(indata, indata, inlen, stream_info->channels, &(ss->chanmap), stream_info->bits) == -1 ) {
1344  if ( bufbuf != NULL )
1345   roar_buffer_free(bufbuf);
1346  return -1;
1347 }
1348#endif
1349
1350 // TODO: this only works in case a we have a amp for the given stream parameters.
1351 if ( !streams_get_flag(id, ROAR_FLAG_HWMIXER) && !streams_get_flag(id, ROAR_FLAG_PASSMIXER) ) {
1352  ROAR_DBG("streams_fill_mixbuffer2(*): CALL roar_amp_pcm(*)...");
1353  if ( roar_amp_pcm(indata, stream_info->bits, indata, 8*inlen / stream_info->bits, stream_info->channels, &(ss->mixer)) == -1 )
1354   return -1;
1355 }
1356
1357 // check codec, bits, channels, rate...
1358 if ( is_the_same ) {
1359  if ( indata != outdata )
1360   memcpy(outdata, indata, inlen);
1361
1362  if ( inlen < outlen )
1363   memset(outdata+inlen, 0, outlen-inlen);
1364 } else {
1365//  if ( roar_conv(outdata, indata, (8*inlen_got*info->rate)/(stream_info->rate * stream_info->bits), stream_info, info) == -1 ) {
1366  ROAR_DBG("streams_fill_mixbuffer2(*): CALL roar_conv2(*)...");
1367  if ( roar_conv2(bufdata, indata, inlen, stream_info, info, outlen) == -1 ) {
1368   if ( bufbuf != NULL )
1369    roar_buffer_free(bufbuf);
1370   return -1;
1371  }
1372
1373//  memset(outdata, 0, outlen);
1374 }
1375
1376 if ( bufbuf != NULL ) {
1377  memcpy(outdata, bufdata, outlen);
1378  roar_buffer_free(bufbuf);
1379 }
1380
1381 streams_ltm_calc(id, stream_info, outdata, outlen);
1382
1383 if ( streams_get_flag(id, ROAR_FLAG_ANTIECHO) ) {
1384  ROAR_DBG("streams_fill_mixbuffer2(*): Calcing antiecho...");
1385  // we can ignore errors here:
1386  if ( stream_outputbuffer_request(id, &bufbuf, buflen) == 0 ) {
1387   if ( roar_buffer_get_data(bufbuf, &bufdata) != -1 )
1388    memcpy(bufdata, outdata, outlen);
1389  }
1390 }
1391
1392 ROAR_DBG("streams_fill_mixbuffer2(*): inlen_got=%llu, stream_info={.bits=%i, .rate=%i,...}", (long long unsigned int)inlen_got, stream_info->bits, stream_info->rate);
1393 s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, (inlen_got*8)/stream_info->bits);
1394
1395 ROAR_DBG("streams_fill_mixbuffer2(*) = 0");
1396 return 0;
1397}
1398
1399
1400int streams_get_mixbuffers (void *** bufferlist, struct roar_audio_info * info, unsigned int pos) {
1401 static void * bufs[ROAR_STREAMS_MAX+1];
1402 int i;
1403 int have = 0;
1404 int dir;
1405
1406 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1407  if ( g_streams[i] != NULL ) {
1408   dir = streams_get_dir(i);
1409
1410   switch (dir) {
1411    case ROAR_DIR_PLAY:
1412    case ROAR_DIR_BIDIR:
1413     break;
1414    case ROAR_DIR_BRIDGE:
1415      if ( g_streams[i]->buffer == NULL )
1416       continue;
1417     break;
1418    default:
1419      continue;
1420   }
1421
1422   if ( streams_get_flag(i, ROAR_FLAG_PAUSE) )
1423    continue;
1424
1425   if ( streams_get_outputbuffer(i, &bufs[have], ROAR_OUTPUT_CALC_OUTBUFSIZE(info)) == -1 ) {
1426    ROAR_ERR("streams_get_mixbuffer(*): Can not alloc output buffer for stream %i, BAD!", i);
1427    ROAR_ERR("streams_get_mixbuffer(*): Ignoring stream for this round.");
1428    continue;
1429   }
1430   if ( streams_fill_mixbuffer2(i, info) == -1 ) {
1431    ROAR_ERR("streams_get_mixbuffer(*): Can not fill output buffer for stream %i, this should not happen", i);
1432    continue;
1433   }
1434
1435//   printf("D: bufs[have=%i] = %p\n", have, bufs[have]);
1436
1437   ROAR_DBG("streams_get_mixbuffers(*):  bufs[have] = %p", bufs[have]);
1438   ROAR_DBG("streams_get_mixbuffers(*): *bufs[have] = 0x%08x...", *(uint32_t*)bufs[have]);
1439
1440   if ( !streams_get_flag(i, ROAR_FLAG_MUTE) )
1441    have++; // we have a new stream!
1442  }
1443 }
1444
1445 bufs[have] = NULL;
1446 //printf("D: bufs[have=%i] = %p\n", have, bufs[have]);
1447
1448 ROAR_DBG("streams_get_mixbuffers(*): have = %i", have);
1449
1450 *bufferlist = bufs;
1451 return have;
1452}
1453
1454
1455int stream_add_buffer  (int id, struct roar_buffer * buf) {
1456 ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = ?", id, buf);
1457
1458 _CHECK_SID(id);
1459
1460 if ( g_streams[id]->buffer == NULL ) {
1461  g_streams[id]->buffer = buf;
1462  ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = 0", id, buf);
1463  return 0;
1464 }
1465
1466 ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = ?", id, buf);
1467 return roar_buffer_add(g_streams[id]->buffer, buf);
1468}
1469
1470int stream_shift_out_buffer   (int id, void * data, size_t * len) {
1471 _CHECK_SID(id);
1472
1473 if ( g_streams[id]->buffer == NULL )
1474  return -1;
1475
1476 return roar_buffer_shift_out(&(g_streams[id]->buffer), data, len);
1477}
1478
1479int stream_shift_buffer   (int id, struct roar_buffer ** buf) {
1480 struct roar_buffer * next;
1481
1482 _CHECK_SID(id);
1483
1484 if ( g_streams[id]->buffer == NULL ) {
1485  *buf = NULL;
1486  return 0;
1487 }
1488
1489 roar_buffer_get_next(g_streams[id]->buffer, &next);
1490
1491 *buf                  = g_streams[id]->buffer;
1492 g_streams[id]->buffer = next;
1493
1494 return 0;
1495}
1496int stream_unshift_buffer (int id, struct roar_buffer *  buf) {
1497 _CHECK_SID(id);
1498
1499 if ( g_streams[id]->buffer == NULL ) {
1500  g_streams[id]->buffer = buf;
1501  return 0;
1502 }
1503
1504 buf->next = NULL;
1505
1506 roar_buffer_add(buf, g_streams[id]->buffer);
1507
1508 g_streams[id]->buffer = buf;
1509
1510 return 0;
1511}
1512
1513int stream_outputbuffer_request(int id, struct roar_buffer ** buf, size_t len) {
1514 register struct roar_stream_server *  ss;
1515 size_t buflen;
1516 void * bufdata;
1517 int ret;
1518
1519 _CHECK_SID(id);
1520
1521 if ( (ss = g_streams[id]) == NULL )
1522  return -1;
1523
1524 if ( buf != NULL ) /* just be be sure */
1525  *buf = NULL;
1526
1527 if ( ss->outputbuffer != NULL ) {
1528  if ( roar_buffer_get_len(ss->outputbuffer, &buflen) == 0 ) {
1529   if ( buflen == len ) {
1530    if ( buf != NULL )
1531     *buf = ss->outputbuffer;
1532    return 0;
1533   } else if ( buflen > len ) {
1534    if ( roar_buffer_set_len(ss->outputbuffer, len) == 0 ) {
1535     if ( buf != NULL )
1536      *buf = ss->outputbuffer;
1537     return 0;
1538    }
1539   }
1540  }
1541
1542  // if the buffer is not suitable:
1543
1544  ret = roar_buffer_free(ss->outputbuffer);
1545  ss->outputbuffer = NULL;
1546  if ( ret == -1 )
1547   return ret;
1548 }
1549
1550 if ( roar_buffer_new(&(ss->outputbuffer), len) == -1 )
1551  return -1;
1552
1553 if ( roar_buffer_get_data(ss->outputbuffer, &bufdata) == -1 ) {
1554  roar_buffer_free(ss->outputbuffer);
1555  ss->outputbuffer = NULL;
1556  return -1;
1557 }
1558
1559 memset(bufdata, 0, len);
1560
1561 if ( buf != NULL )
1562  *buf = ss->outputbuffer;
1563
1564 return 0;
1565}
1566
1567int stream_outputbuffer_destroy(int id) {
1568 int ret;
1569 register struct roar_stream_server *  ss;
1570
1571 _CHECK_SID(id);
1572
1573 if ( (ss = g_streams[id]) == NULL )
1574  return -1;
1575
1576 if ( ss->outputbuffer != NULL ) {
1577  ret = roar_buffer_free(ss->outputbuffer);
1578  ss->outputbuffer = NULL;
1579  return ret;
1580 }
1581
1582 return 0;
1583}
1584
1585int stream_prethru_add(int id, struct roar_buffer * buf) {
1586 register struct roar_stream_server *  ss;
1587
1588 _CHECK_SID(id);
1589
1590 if ( (ss = g_streams[id]) == NULL )
1591  return -1;
1592
1593 if ( ss->prethru == NULL ) {
1594  ss->prethru = buf;
1595  return 0;
1596 }
1597
1598 if ( roar_buffer_add(ss->prethru, buf) == -1 ) {
1599  return -1;
1600 }
1601
1602 return 0;
1603}
1604
1605int stream_prethru_add_data(int id, void ** buf, size_t len) {
1606 struct roar_buffer * buffer;
1607
1608 _CHECK_SID(id);
1609
1610 if ( roar_buffer_new(&buffer, len) == -1 )
1611  return -1;
1612
1613 if ( roar_buffer_get_data(buffer, buf) == -1 ) {
1614  roar_buffer_free(buffer);
1615  return -1;
1616 }
1617
1618 if ( stream_prethru_add(id, buffer) == -1 ) {
1619  roar_buffer_free(buffer);
1620  return -1;
1621 }
1622
1623 return 0;
1624}
1625
1626int stream_prethru_destroy(int id) {
1627 int ret;
1628 register struct roar_stream_server *  ss;
1629
1630 _CHECK_SID(id);
1631
1632 if ( (ss = g_streams[id]) == NULL )
1633  return -1;
1634
1635 if ( ss->prethru != NULL ) {
1636  ret = roar_buffer_free(ss->prethru);
1637  ss->prethru = NULL;
1638  return ret;
1639 }
1640
1641 return 0;
1642}
1643
1644int stream_prethru_send(int dst, int src) {
1645 struct roar_stream_server *  dst_ss, * src_ss;
1646 struct roar_buffer * bufbuf;
1647 void * bufdata;
1648 size_t buflen;
1649
1650 ROAR_DBG("stream_prethru_send(dst=%i, src=%i) = ?", dst, src);
1651
1652 _CHECK_SID(dst);
1653 _CHECK_SID(src);
1654
1655 if ( (dst_ss = g_streams[dst]) == NULL )
1656  return -1;
1657
1658 if ( (src_ss = g_streams[src]) == NULL )
1659  return -1;
1660
1661 bufbuf = src_ss->prethru;
1662
1663 ROAR_DBG("stream_prethru_send(dst=%i, src=%i): prethru buffer at %p", dst, src, bufbuf);
1664
1665 while (bufbuf != NULL) {
1666  ROAR_DBG("stream_prethru_send(dst=%i, src=%i): looping with buffer at %p", dst, src, bufbuf);
1667
1668  if ( roar_buffer_get_data(bufbuf, &bufdata) == -1 )
1669   return -1;
1670
1671  if ( roar_buffer_get_len(bufbuf, &buflen) == -1 )
1672   return -1;
1673
1674  if ( stream_vio_s_write(dst_ss, bufdata, buflen) != buflen )
1675   return -1;
1676
1677  if ( roar_buffer_get_next(bufbuf, &bufbuf) == -1 )
1678   return -1;
1679 }
1680
1681 ROAR_DBG("stream_prethru_send(dst=%i, src=%i) = 0", dst, src);
1682 return 0;
1683}
1684
1685int streams_check  (int id) {
1686 int fh;
1687 ssize_t req, realreq, done;
1688 struct roar_stream        *   s;
1689 struct roar_stream_server *  ss;
1690 struct roar_buffer        *   b;
1691 char                      * buf;
1692// char                        tmp;
1693
1694 _CHECK_SID(id);
1695
1696 ROAR_DBG("streams_check(id=%i) = ?", id);
1697
1698 s = ROAR_STREAM(ss = g_streams[id]);
1699
1700 if ( (fh = s->fh) == -1 )
1701  return 0;
1702
1703 if ( streams_get_flag(id, ROAR_FLAG_PAUSE) )
1704  return 0;
1705
1706 switch (s->dir) {
1707  case ROAR_DIR_LIGHT_IN:
1708#ifndef ROAR_WITHOUT_DCOMP_LIGHT
1709    return light_check_stream(id);
1710#else
1711    streams_delete(id);
1712    return -1;
1713#endif
1714   break;
1715  case ROAR_DIR_MIDI_IN:
1716#ifndef ROAR_WITHOUT_DCOMP_MIDI
1717    return midi_check_stream(id);
1718#else
1719    streams_delete(id);
1720    return -1;
1721#endif
1722   break;
1723  case ROAR_DIR_RAW_IN:
1724#ifndef ROAR_WITHOUT_DCOMP_RAW
1725    return raw_check_stream(id);
1726#else
1727    streams_delete(id);
1728    return -1;
1729#endif
1730   break;
1731  case ROAR_DIR_RDTCS_IN:
1732#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1733    return rdtcs_check_stream(id);
1734#else
1735    streams_delete(id);
1736    return -1;
1737#endif
1738   break;
1739  case ROAR_DIR_PLAY:
1740  case ROAR_DIR_BIDIR:
1741   break;
1742  default:
1743/*
1744    ROAR_WARN("streams_check(id=%i): Read event on non input stream of type/dir %s", id, roar_dir2str(s->dir));
1745    errno = 0;
1746    req = stream_vio_s_read(ss, &tmp, 1);
1747    ROAR_DBG("streams_check(id=%i): stream_vio_s_read(ss, &tmp, 1) = %li // errno=%s(%i)", id, req, strerror(errno), errno);
1748    if ( req == 1 ) {
1749     ROAR_ERR("streams_check(id=%i): Client violates protocol, got one byte of data on output stream, kicking stream");
1750     streams_delete(id);
1751     return -1;
1752    }
1753*/
1754    return 0;
1755   break;
1756 }
1757
1758 ROAR_DBG("streams_check(id=%i): fh = %i", id, fh);
1759
1760/*
1761 ROAR_DBG("streams_check(id=%i): ROAR_OUTPUT_BUFFER_SAMPLES=%i, s->info.channels=%i, s->info.bits=%i, s->info.rat=%i, g_sa->rate=%i", id, ROAR_OUTPUT_BUFFER_SAMPLES, s->info.channels, s->info.bits, s->info.rate, g_sa->rate);
1762*/
1763
1764 req  = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info)); // optimal size
1765// req  = ROAR_OUTPUT_BUFFER_SAMPLES * s->info.channels * (s->info.bits / 8) * ((float)s->info.rate/g_sa->rate);
1766 req += ss->need_extra; // bytes left we sould get....
1767
1768 ROAR_DBG("streams_check(id=%i): asking for %i bytes", id, req);
1769
1770 if ( roar_buffer_new(&b, req) == -1 ) {
1771  ROAR_ERR("streams_check(*): Can not alloc buffer space!");
1772  ROAR_DBG("streams_check(*) = -1");
1773  return -1;
1774 }
1775
1776 roar_buffer_get_data(b, (void **)&buf);
1777
1778 ROAR_DBG("streams_check(id=%i): buffer is up and ready ;)", id);
1779 ROAR_DBG("streams_check(id=%i): asking for %i bytes", id, req);
1780
1781 if ( ss->codecfilter == -1 ) {
1782  realreq = req;
1783/*
1784  req = read(fh, buf, req);
1785  if ( req < realreq ) { // we can do this as the stream is in nonblocking mode!
1786   if ( (realreq = read(fh, buf+req, realreq-req)) > 0 )
1787    req += realreq;
1788  }
1789*/
1790  done = 0;
1791  while (req > 0 && done != realreq) {
1792   if ( (req = stream_vio_s_read(ss, buf+done, realreq-done)) > 0 )
1793    done += req;
1794  }
1795  req = done;
1796
1797  roar_buffer_get_data(b, (void **)&buf);
1798 } else {
1799  req = codecfilter_read(ss->codecfilter_inst, ss->codecfilter, buf, req);
1800 }
1801
1802 if ( req > 0 ) {
1803  ROAR_DBG("streams_check(id=%i): got %i bytes", id, req);
1804
1805  roar_buffer_set_len(b, req);
1806
1807  if ( stream_add_buffer(id, b) != -1 )
1808   return 0;
1809
1810  ROAR_ERR("streams_check(id=%i): something is wrong, could not add buffer to stream!", id);
1811  roar_buffer_free(b);
1812 } else {
1813  ROAR_DBG("streams_check(id=%i): read() = %i // errno: %s", id, req, strerror(errno));
1814#ifdef ROAR_HAVE_LIBVORBISFILE
1815  if ( errno != EAGAIN && errno != ESPIPE ) { // libvorbis file trys to seek a bit ofen :)
1816#else
1817  if ( errno != EAGAIN ) {
1818#endif
1819   ROAR_DBG("streams_check(id=%i): EOF!", id);
1820   streams_delete(id);
1821   ROAR_DBG("streams_check(id=%i) = 0", id);
1822  }
1823  roar_buffer_free(b);
1824  return 0;
1825 }
1826
1827
1828 ROAR_DBG("streams_check(id=%i) = -1", id);
1829 return -1;
1830}
1831
1832
1833#define _return(x) return (x)
1834int streams_send_mon   (int id) {
1835// int fh;
1836 struct roar_stream        *   s;
1837 struct roar_stream_server *  ss;
1838 struct roar_buffer        *  bufbuf = NULL;
1839 struct roar_remove_state     removalstate;
1840 void  * ip;
1841 void  * obuf;
1842 int     olen;
1843 int     is_the_same     = 1;
1844 int     is_vol_eq       = 1;
1845 int     antiecho        = 0;
1846 ssize_t ret;
1847
1848 _CHECK_SID(id);
1849
1850 ROAR_DBG("streams_send_mon(id=%i) = ?", id);
1851
1852 s = ROAR_STREAM((ss = g_streams[id]));
1853
1854/*
1855 if ( (fh = s->fh) == -1 )
1856  return 0;
1857*/
1858
1859 if ( !ss->ready )
1860  return 0;
1861
1862 if ( g_config->jumbo_mtu )
1863  roar_vio_sync(ss->viop);
1864
1865 if ( streams_get_flag(id, ROAR_FLAG_PAUSE) )
1866  return 0;
1867
1868 switch (s->dir) {
1869  case ROAR_DIR_LIGHT_OUT:
1870#ifndef ROAR_WITHOUT_DCOMP_LIGHT
1871    return light_send_stream(id);
1872#else
1873    streams_delete(id);
1874    return -1;
1875#endif
1876   break;
1877  case ROAR_DIR_MIDI_OUT:
1878#ifndef ROAR_WITHOUT_DCOMP_MIDI
1879    return midi_send_stream(id);
1880#else
1881    streams_delete(id);
1882    return -1;
1883#endif
1884   break;
1885  case ROAR_DIR_RDTCS_OUT:
1886#ifndef ROAR_WITHOUT_DCOMP_RDTCS
1887    return rdtcs_send_stream(id);
1888#else
1889    streams_delete(id);
1890    return -1;
1891#endif
1892   break;
1893
1894  case ROAR_DIR_COMPLEX_OUT:
1895    // send a tick:
1896    if ( ss->codecfilter != -1 ) {
1897     if ( codecfilter_write(ss->codecfilter_inst, ss->codecfilter, NULL, 0) == 0 )
1898      if ( ss->state != ROAR_STREAMSTATE_OLD ) {
1899       //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
1900       _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
1901      }
1902    }
1903    return 0;
1904   break;
1905
1906  case ROAR_DIR_OUTPUT:
1907    if ( g_standby )
1908     return 0;
1909  case ROAR_DIR_MONITOR:
1910  case ROAR_DIR_BIDIR:
1911   break;
1912
1913  default:
1914    return 0;
1915   break;
1916 }
1917
1918
1919 ROAR_DBG("streams_send_mon(id=%i): fh = %i", id, s->fh);
1920
1921 if ( s->info.channels != g_sa->channels || s->info.bits  != g_sa->bits ||
1922      s->info.rate     != g_sa->rate     || s->info.codec != g_sa->codec  )
1923  is_the_same = 0;
1924
1925 if ( !streams_get_flag(id, ROAR_FLAG_HWMIXER) ) {
1926  is_vol_eq = need_vol_change(g_sa->channels, &(ss->mixer)) ? 0 : 1;
1927 }
1928
1929 if ( streams_get_flag(id, ROAR_FLAG_ANTIECHO) )
1930  antiecho = 1;
1931
1932 if ( !is_the_same || !is_vol_eq || antiecho ) {
1933  olen = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info)); // we hope g_output_buffer_len
1934                                                  // is ROAR_OUTPUT_CALC_OUTBUFSIZE(g_sa) here
1935  if ( stream_outputbuffer_request(id, &bufbuf, ROAR_OUTPUT_CALC_OUTBUFSIZE_MAX(&(s->info), g_sa)) == -1 )
1936   return -1;
1937
1938  if ( roar_buffer_get_data(bufbuf, &obuf) == -1 ) {
1939   _return(-1);
1940  }
1941
1942  ROAR_DBG("streams_send_mon(id=%i): obuf=%p, olen=%i", id, obuf, olen);
1943 } else {
1944  obuf = g_output_buffer;
1945  olen = g_output_buffer_len;
1946 }
1947
1948 ip = g_output_buffer;
1949
1950 if ( antiecho ) {
1951  ROAR_DBG("streams_send_mon(id=%i): antiecho=%i", id, antiecho);
1952  if ( roar_remove_init(&removalstate) == -1 ) {
1953   _return(-1);
1954  }
1955
1956  ROAR_DBG("streams_send_mon(id=%i): antiecho=%i", id, antiecho);
1957  if ( roar_remove_so(obuf, ip, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa->bits, &removalstate) == -1 ) {
1958   ROAR_DBG("streams_send_mon(id=%i): anti echo failed", id);
1959   _return(-1);
1960  }
1961  ROAR_DBG("streams_send_mon(id=%i): antiecho=%i", id, antiecho);
1962 }
1963
1964 if ( !is_vol_eq ) {
1965  if ( roar_amp_pcm(obuf, g_sa->bits, ip, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa->channels, &(ss->mixer)) == -1 ) {
1966   _return(-1);
1967  }
1968
1969  ip = obuf;
1970 }
1971
1972 streams_ltm_calc(id, &(s->info), ip, (ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels*g_sa->bits)/8);
1973
1974 if ( !is_the_same ) {
1975  if ( roar_conv(obuf, ip, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa, &(s->info)) == -1 ) {
1976   _return(-1);
1977  }
1978 }
1979
1980 errno = 0;
1981
1982 if ( ss->codecfilter == -1 ) {
1983  ROAR_DBG("streams_send_mon(id=%i): not a CF stream", id);
1984  if ( s->fh == -1 && roar_vio_get_fh(&(ss->vio)) == -1 ) {
1985   ROAR_DBG("streams_send_mon(id=%i) = 0", id);
1986   _return(0);
1987  }
1988
1989  ROAR_DBG("streams_send_mon(id=%i) = ?", id);
1990
1991  if ( (ret = stream_vio_s_write(ss, obuf, olen)) == olen ) {
1992   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
1993   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
1994    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
1995    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
1996   }
1997   ROAR_DBG("streams_send_mon(id=%i) = 0", id);
1998   _return(0);
1999  }
2000
2001  ROAR_DBG("streams_send_mon(id=%i) = ?", id);
2002
2003  if ( ret > 0 && errno == 0 ) {
2004   ROAR_WARN("streams_send_mon(id=%i): Overrun in stream: wrote %i of %i bytes, %i bytes missing", id, (int)ret, olen, olen-(int)ret);
2005   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), ret)*s->info.channels);
2006   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2007    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2008    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2009   }
2010   _return(0);
2011  }
2012 } else {
2013  errno = 0;
2014  if ( codecfilter_write(ss->codecfilter_inst, ss->codecfilter, obuf, olen)
2015            == olen ) {
2016   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
2017   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2018    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2019    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2020   }
2021   _return(0);
2022  } else { // we cann't retry on codec filetered streams
2023   if ( errno != EAGAIN ) {
2024    streams_delete(id);
2025    _return(-1);
2026   }
2027  }
2028 }
2029
2030 if ( errno == EAGAIN ) {
2031  // ok, the client blocks for a moment, we try to sleep a bit an retry in the hope not to
2032  // make any gapes in any output because of this
2033
2034#ifdef ROAR_HAVE_USLEEP
2035  usleep(100); // 0.1ms
2036#endif
2037
2038  if ( stream_vio_s_write(ss, obuf, olen) == olen ) {
2039   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
2040   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2041    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2042    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2043   }
2044   _return(0);
2045  } else if ( errno == EAGAIN ) {
2046   ROAR_WARN("streams_send_mon(id=%i): Can not send data to client: %s", id, strerror(errno));
2047   _return(0);
2048  }
2049 }
2050
2051 // ug... error... delete stream!
2052
2053 streams_delete(id);
2054
2055 _return(-1);
2056}
2057#undef _return
2058
2059int streams_send_filter(int id) {
2060 int fh;
2061 int have = 0;
2062 int len;
2063 struct roar_stream        *   s;
2064 struct roar_stream_server *  ss;
2065
2066 _CHECK_SID(id);
2067
2068 ROAR_DBG("streams_send_filter(id=%i) = ?", id);
2069
2070 s = ROAR_STREAM(ss = g_streams[id]);
2071
2072 if ( (fh = s->fh) == -1 )
2073  return 0;
2074
2075 if ( s->dir != ROAR_DIR_FILTER )
2076  return 0;
2077
2078 if ( streams_get_flag(id, ROAR_FLAG_PAUSE) )
2079  return 0;
2080
2081
2082 ROAR_DBG("streams_send_filter(id=%i): fh = %i", id, fh);
2083
2084 if ( stream_vio_s_write(ss, g_output_buffer, g_output_buffer_len) == g_output_buffer_len ) {
2085  while ( have < g_output_buffer_len ) {
2086   if ( (len = stream_vio_s_read(ss, g_output_buffer+have, g_output_buffer_len-have)) < 1 ) {
2087    streams_delete(id);
2088    return -1;
2089   }
2090   have += len;
2091  }
2092  return 0;
2093 }
2094
2095 // ug... error... delete stream!
2096
2097 streams_delete(id);
2098
2099 return -1;
2100}
2101
2102
2103// VIO:
2104
2105ssize_t stream_vio_read (int stream, void *buf, size_t count) {
2106 _CHECK_SID(stream);
2107
2108 return stream_vio_s_read(g_streams[stream], buf, count);
2109}
2110
2111ssize_t stream_vio_write(int stream, void *buf, size_t count) {
2112 _CHECK_SID(stream);
2113
2114 return stream_vio_s_write(g_streams[stream], buf, count);
2115}
2116
2117
2118ssize_t stream_vio_s_read (struct roar_stream_server * stream, void *buf, size_t count) {
2119 void    * orig_buf = buf;
2120  size_t   len      =  0;
2121 ssize_t   r        = -1;
2122 int       i;
2123
2124 errno = 0;
2125
2126 if ( !stream )
2127  return -1;
2128
2129 //roar_vio_set_fh(&(stream->vio), ROAR_STREAM(stream)->fh);
2130
2131 if ( ! stream->vio.read )
2132  return -1;
2133
2134 while ( (r = roar_vio_read(&(stream->vio), buf, count)) > 0 ) {
2135  len   += r;
2136  buf   += r;
2137  count -= r;
2138  if ( count == 0 )
2139   break;
2140 }
2141
2142 if ( len == 0 && r == -1 )
2143  return -1;
2144
2145 if ( streams_thru_num ) {
2146  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
2147   if ( g_streams[i] != NULL && ROAR_STREAM(g_streams[i])->pos_rel_id == ROAR_STREAM(stream)->id ) {
2148    if ( ROAR_STREAM(g_streams[i])->dir == ROAR_DIR_THRU ) {
2149     if ( g_streams[i]->ready ) {
2150      if ( stream_vio_write(i, orig_buf, len) != len )
2151       streams_delete(i);
2152
2153      if ( g_streams[i] != NULL ) {
2154       if ( g_streams[i]->state != ROAR_STREAMSTATE_OLD ) {
2155        //ROAR_INFO("stream_vio_s_read(*): (stream: %i) stream state: %s->old", ROAR_DBG_INFO_VERBOSE, i, roar_streamstate2str(g_streams[i]->state));
2156        _streams_change_state(g_streams[i], ROAR_STREAMSTATE_OLD, "stream_vio_s_read");
2157       }
2158      }
2159     }
2160    }
2161   }
2162  }
2163 }
2164
2165 return len;
2166}
2167
2168ssize_t stream_vio_s_write(struct roar_stream_server * stream, void *buf, size_t count) {
2169 int i;
2170
2171 errno = 0;
2172
2173 if ( !stream )
2174  return -1;
2175
2176/*
2177 if ( roar_vio_get_fh(&(stream->vio)) == -1 && ROAR_STREAM(stream)->fh != -1 )
2178  roar_vio_set_fh(&(stream->vio), ROAR_STREAM(stream)->fh);
2179*/
2180
2181// ROAR_WARN("stream_vio_s_write(*): writing...");
2182
2183 if ( streams_thru_num ) {
2184  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
2185   if ( g_streams[i] != NULL && ROAR_STREAM(g_streams[i])->pos_rel_id == ROAR_STREAM(stream)->id ) {
2186    if ( ROAR_STREAM(g_streams[i])->dir == ROAR_DIR_THRU ) {
2187     if ( g_streams[i]->ready ) {
2188      if ( g_streams[i]->state == ROAR_STREAMSTATE_NEW ) {
2189       if ( streams_get_flag(i, ROAR_FLAG_PRETHRU) == 1 ) {
2190        if ( stream_prethru_send(i, ROAR_STREAM(stream)->id) == -1 ) {
2191         streams_delete(i);
2192        }
2193       }
2194      }
2195
2196      if ( stream_vio_write(i, buf, count) != count ) {
2197       streams_delete(i);
2198      }
2199
2200      if ( g_streams[i] != NULL ) {
2201       if ( g_streams[i]->state != ROAR_STREAMSTATE_OLD ) {
2202        //ROAR_INFO("stream_vio_s_write(*): (stream: %i) stream state: %s->old", ROAR_DBG_INFO_VERBOSE, i, roar_streamstate2str(g_streams[i]->state));
2203        _streams_change_state(g_streams[i], ROAR_STREAMSTATE_OLD, "stream_vio_s_write");
2204       }
2205      }
2206     }
2207    }
2208   }
2209  }
2210 }
2211
2212 if ( g_config->jumbo_mtu ) {
2213  if ( stream->viop != &(stream->jumbo) ) {
2214   if ( roar_vio_open_jumbo(&(stream->jumbo), &(stream->vio), g_config->jumbo_mtu) != -1 ) {
2215    // if that works we continue using the jumbo vio,
2216    // in case it didn't we dont, just use normal VIO.
2217    stream->viop = &(stream->jumbo);
2218   }
2219  }
2220 }
2221
2222 return roar_vio_write(stream->viop, buf, count);
2223}
2224
2225//ll
Note: See TracBrowser for help on using the repository browser.