source: roaraudio/roard/streams.c @ 5624:ec1593cc8525

Last change on this file since 5624:ec1593cc8525 was 5624:ec1593cc8525, checked in by phi, 12 years ago

Added support for RePlayGain? (RPG) control (See: #300)

File size: 67.6 KB
Line 
1//streams.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2012
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// declared 'extern'
29struct roar_stream_server * g_streams[ROAR_STREAMS_MAX];
30
31#define _CHECK_SID_RET(id,ret) if ( (id) < 0 || (id) > ROAR_STREAMS_MAX || g_streams[(id)] == NULL ) return (ret)
32#define _CHECK_SID(id)         _CHECK_SID_RET((id), -1)
33
34static int streams_thru_num     =  0;
35static int streams_sync_num     =  0;
36int streams_recsource_id = -1;
37
38static const struct rolestack * streams_rolestack = NULL;
39static int streams_role_num     =  0;
40
41
42static void _streams_change_state(struct roar_stream_server * s, const int new, const char * func) {
43 register int id  = ROAR_STREAM(s)->id;
44 register int old = s->state;
45
46 s->state = new;
47
48 if ( func == NULL ) {
49  func = "(unknown)";
50 }
51
52 ROAR_INFO("_streams_change_state[by %s](id=%i): stream state: %s->%s", ROAR_DBG_INFO_VERBOSE,
53            func,
54            ROAR_STREAM(s)->id,
55            roar_streamstate2str(old), roar_streamstate2str(new));
56
57 roar_notify_core_emit_simple(ROAR_OE_BASICS_CHANGE_STATE, -1, id, ROAR_OT_STREAM, old, new, NULL, 0);
58}
59
60void streams_change_sync_num(int id, int diff) {
61 struct roar_stream_server * ss;
62 int i;
63
64 if ( diff != 0 )
65  if ( streams_get_dir(id) != ROAR_DIR_OUTPUT )
66   return;
67
68 ROAR_INFO("streams_change_sync_num(id=%i, diff=%i): Number of sync streams changed from %i to %i",
69           ROAR_DBG_INFO_VERBOSE,
70           id, diff,
71           streams_sync_num, streams_sync_num + diff);
72 streams_sync_num += diff;
73
74 if ( !streams_sync_num && alive ) {
75  ROAR_INFO("streams_change_sync_num(id=%i, diff=%i): Number of sync streams changed to zero. Bad.",
76            ROAR_DBG_INFO_VERBOSE, id, diff
77            );
78
79  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
80   if ( (ss = g_streams[i]) == NULL )
81    continue;
82
83   if ( ROAR_STREAM(ss)->dir != ROAR_DIR_OUTPUT )
84    continue;
85
86   if ( !ss->ready )
87    continue;
88
89   if ( ss->state == ROAR_STREAMSTATE_CLOSING )
90    continue;
91
92   if ( streams_get_flag(i, ROAR_FLAG_PRIMARY) ) {
93    ROAR_DBG("streams_change_sync_num(*): try to set sync on primary stream %i", i);
94    streams_set_flag(i, ROAR_FLAG_SYNC);
95    if ( streams_sync_num )
96     return;
97   }
98  }
99
100  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
101   if ( (ss = g_streams[i]) == NULL )
102    continue;
103
104   if ( ROAR_STREAM(ss)->dir != ROAR_DIR_OUTPUT )
105    continue;
106
107   if ( !ss->ready )
108    continue;
109
110   if ( ss->state == ROAR_STREAMSTATE_CLOSING )
111    continue;
112
113   if ( !streams_get_flag(i, ROAR_FLAG_PRIMARY) ) {
114    ROAR_DBG("streams_change_sync_num(*): try to set sync on non-primary stream %i", i);
115    streams_set_flag(i, ROAR_FLAG_SYNC);
116    if ( streams_sync_num )
117     return;
118   }
119  }
120
121  ROAR_INFO("streams_change_sync_num(id=%i, diff=%i): Can not auto set sync flag to an output. Very Bad",
122            ROAR_DBG_INFO_VERBOSE, id, diff
123            );
124  ROAR_WARN("streams_change_sync_num(id=%i, diff=%i): Lost all sync streams and failed to set a new one. Very Bad.",
125            id, diff);
126 }
127}
128
129int streams_init (void) {
130 int i;
131
132 streams_rolestack = rolestack_get_role(-1); // get default
133
134 for (i = 0; i < ROAR_STREAMS_MAX; i++)
135  g_streams[i] = NULL;
136
137 return 0;
138}
139
140int streams_free (void) {
141 int i;
142
143 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
144  if ( g_streams[i] != NULL ) {
145   streams_delete(i);
146  }
147 }
148
149 return 0;
150}
151
152
153int streams_new    (void) {
154 int i, j;
155 struct roar_stream        * n = NULL;
156 struct roar_stream_server * s = NULL;
157
158#ifdef ROAR_SUPPORT_LISTEN
159 if ( g_terminate && !g_no_listen ) // don't accept new streams in case of termination state
160  return -1;
161#else
162 if ( g_terminate )                 // don't accept new streams in case of termination state
163  return -1;
164#endif
165
166 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
167  if ( g_streams[i] == NULL ) {
168   s = ROAR_STREAM_SERVER(n = ROAR_STREAM(roar_mm_malloc(sizeof(struct roar_stream_server))));
169   if ( n == NULL ) {
170    ROAR_ERR("streams_new(void): can not allocate memory for new stream: %s", strerror(errno));
171    ROAR_DBG("streams_new(void) = -1");
172    return -1;
173   }
174
175   memset(s, 0, sizeof(struct roar_stream_server));
176
177   n->id         = i;
178   n->fh         = -1;
179   n->pos_rel_id = -1;
180/*
181   n->database   = NULL;
182   n->dataoff    = NULL;
183   n->datalen    = 0;
184   n->offset     = 0;
185*/
186   n->pos        = 0;
187
188   s->name            = NULL;
189
190   s->state           = ROAR_STREAMSTATE_INITING;
191
192   s->client          = -1;
193   s->socktype        = ROAR_SOCKET_TYPE_UNKNOWN;
194   s->buffer          = NULL;
195   s->need_extra      =  0;
196   s->output          = NULL;
197   s->is_new          =  1;
198   s->codecfilter     = -1;
199   s->pre_underruns   =  0;
200   s->post_underruns  =  0;
201   s->delay           =  0;
202   s->codec_orgi      = -1;
203   s->primary         =  0;
204   s->ready           =  0;
205   s->outputbuffer    = NULL;
206   s->prethru         = NULL;
207   s->mixer_stream    = -1;
208   s->role            = ROAR_ROLE_UNKNOWN;
209   s->parent_stream   = -1;
210   s->single_sink_c   =  0;
211   s->single_sink_self_c =  0;
212
213   s->mixer.scale     = 65535;
214   s->mixer.rpg_mul   = 1;
215   s->mixer.rpg_div   = 1;
216   for (j = 0; j < ROAR_MAX_CHANNELS; j++)
217    s->mixer.mixer[j] = 65535;
218
219#ifdef ROAR_SUPPORT_META
220   for (j = 0; j < ROAR_META_MAX_PER_STREAM; j++) {
221    s->meta[j].type   = ROAR_META_TYPE_NONE;
222    s->meta[j].key[0] = 0;
223    s->meta[j].value  = NULL;
224   }
225#endif
226
227   roar_vio_clear_calls(&(s->vio));
228   roar_vio_clear_calls(&(s->jumbo));
229   s->viop      = &(s->vio);
230   s->driver_id = -1;
231   s->flags     =  ROAR_FLAG_NONE;
232
233#ifndef ROAR_WITHOUT_DCOMP_MIXER
234   s->mixerstream =  NULL;
235#endif
236
237   s->rpgmode = ROAR_RPGMODE_DEFAULT;
238
239   //roardsp_fchain_init(&(s->fc));
240
241   g_streams[i] = s;
242   counters_inc(streams, 1);
243   ROAR_INFO("streams_new(void): New stream %i created (state=initing)", ROAR_DBG_INFO_VERBOSE, i);
244   ROAR_DBG("streams_new(void): n->id=%i", n->id);
245   roar_notify_core_emit_snoargs(ROAR_OE_BASICS_NEW, -1, i, ROAR_OT_STREAM);
246   ROAR_DBG("streams_new(void) = %i", i);
247   return i;
248  }
249 }
250
251 return -1;
252}
253
254int streams_delete (int id) {
255 struct roar_stream_server * s;
256 int prim;
257 int no_vio_close = 0;
258 int i;
259 int client;
260
261 _CHECK_SID(id);
262
263 if ( (s = g_streams[id]) == NULL )
264  return 0;
265
266 ROAR_DBG("streams_delete(id=%i) = ?", id);
267 ROAR_DBG("streams_delete(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(s)->id);
268
269 // in case we are allready closing it...
270 if ( s->state == ROAR_STREAMSTATE_CLOSING )
271  return 0;
272
273 _streams_change_state(s, ROAR_STREAMSTATE_CLOSING, "streams_delete");
274 roar_notify_core_emit_snoargs(ROAR_OE_BASICS_DELETE, -1, id, ROAR_OT_STREAM);
275
276 streams_set_role(id, -1);
277
278 prim = s->primary;
279
280 if ( prim )
281  alive = 0;
282
283 if ( s->flags & ROAR_FLAG_SINGLESINK )
284  streams_set_single_sink(id, 1);
285
286 counters_inc(streams, -1);
287
288 if ( streams_get_flag(id, ROAR_FLAG_RECSOURCE) == 1 )
289  streams_reset_flag(id, ROAR_FLAG_RECSOURCE);
290
291 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
292  if ( g_streams[i] != NULL && ROAR_STREAM(g_streams[i])->pos_rel_id == id ) {
293   switch (ROAR_STREAM(g_streams[i])->dir) {
294    case ROAR_DIR_THRU:
295    case ROAR_DIR_RAW_IN:
296      if ( i != id )
297       streams_delete(i);
298     break;
299    default:
300      if ( streams_get_flag(i, ROAR_FLAG_VIRTUAL) == 1 ) {
301       if ( i != id ) {
302        ROAR_DBG("streams_delete(id=%i): Deleting virtual child stream %i", id, i);
303        streams_delete(i);
304       }
305      } else {
306       ROAR_STREAM(g_streams[i])->pos_rel_id = -1;
307      }
308   }
309  }
310 }
311
312 if ( ROAR_STREAM(s)->dir == ROAR_DIR_THRU )
313  streams_thru_num--;
314
315 if ( streams_get_flag(id, ROAR_FLAG_VIRTUAL) == 1 ) {
316  // we un-group the stream here to avoid a client deleting the parent deleting the client deleting ...
317  i      = ROAR_STREAM(s)->pos_rel_id;
318  if ( i != -1 ) {
319   ROAR_STREAM(s)->pos_rel_id = -1;
320   client = streams_get_client(id);
321   streams_set_client(id, -1);
322   ROAR_DBG("streams_delete(id=%i): Stream has flag virtual, notifying parent stream %i", id, i);
323   streams_ctl(i, ROAR_CODECFILTER_CTL_VIRTUAL_DELETE|ROAR_STREAM_CTL_TYPE_INT, &id);
324   ROAR_DBG("streams_delete(id=%i): Notify send to stream %i", id, i);
325   streams_set_client(id, client);
326   ROAR_STREAM(s)->pos_rel_id = i;
327  }
328 }
329
330#ifdef ROAR_SUPPORT_META
331 // delete meta data form other meta streams if needed
332 if ( streams_get_flag(id, ROAR_FLAG_META) == 1 ) {
333  ROAR_DBG("streams_delete(id=%i): deleting meta stream!", id);
334  stream_meta_clear(id);
335  stream_meta_finalize(id);
336 }
337#endif
338
339 if ( s->codecfilter != -1 ) {
340  codecfilter_close(s->codecfilter_inst, s->codecfilter);
341  s->codecfilter_inst = NULL;
342  s->codecfilter = -1;
343 }
344
345 if ( s->driver_id != -1 ) {
346  driver_closevio(&(s->vio), s->driver_id);
347  roar_vio_clear_calls(&(s->vio));
348  s->driver_id = -1;
349  no_vio_close =  1;
350 }
351
352#ifndef ROAR_WITHOUT_DCOMP_MIXER
353 if ( s->mixerstream != NULL ) {
354  hwmixer_close(id);
355 }
356#endif
357
358 // all IO is no disconnected:
359 s->ready = 0;
360
361 // re-try reset after all IO is disconnected.
362 if ( streams_get_flag(id, ROAR_FLAG_RECSOURCE) == 1 )
363  streams_reset_flag(id, ROAR_FLAG_RECSOURCE);
364
365 //roardsp_fchain_uninit(&(s->fc));
366
367 if ( s->client != -1 ) {
368  ROAR_DBG("streams_delete(id=%i): Stream is owned by client %i", id, g_streams[id]->client);
369  client_stream_delete(s->client, id);
370 }
371
372 stream_outputbuffer_destroy(id);
373 stream_prethru_destroy(id);
374
375 if ( s->buffer != NULL )
376  roar_buffer_free(s->buffer);
377
378 if ( s->output != NULL )
379  roar_mm_free(s->output);
380
381/*
382 if ( ROAR_STREAM(s)->fh != -1 )
383  close(ROAR_STREAM(s)->fh);
384*/
385
386 if ( s->flags & ROAR_FLAG_SYNC )
387  streams_change_sync_num(id, -1);
388
389 if ( !no_vio_close )
390  roar_vio_close(s->viop);
391
392 if ( s->name != NULL )
393  roar_mm_free(s->name);
394
395 roar_mm_free(s);
396
397 g_streams[id] = NULL;
398
399 if ( prim && alive ) {
400  alive = 0;
401  clean_quit();
402 }
403
404 ROAR_INFO("streams_delete(id=%i): stream deleted", ROAR_DBG_INFO_VERBOSE, id);
405 ROAR_DBG("streams_delete(id=%i) = 0", id);
406 return 0;
407}
408
409int streams_set_client (int id, int client) {
410
411 _CHECK_SID(id);
412
413 ROAR_DBG("streams_set_client(id=%i): g_streams[id]->id=%i", id, ROAR_STREAM(g_streams[id])->id);
414 g_streams[id]->client = client;
415
416 return 0;
417}
418
419int streams_get_client (int id) {
420 _CHECK_SID(id);
421
422 return g_streams[id]->client;
423}
424
425int streams_set_dir    (int id, int dir, int defaults) {
426 struct roar_stream_server * ss;
427 int mixer;
428
429 _CHECK_SID(id);
430
431 if ( (ss = g_streams[id]) == NULL ) {
432  ROAR_ERR("streams_set_dir(id=%i, dir=%i, defaults=%i) = -1 // error=NOENT", id, dir, defaults);
433  roar_err_set(ROAR_ERROR_NOENT);
434  return -1;
435 }
436
437 ROAR_STREAM(ss)->dir = dir;
438
439 if ( dir == ROAR_DIR_THRU )
440  streams_thru_num++;
441
442 if ( defaults ) {
443  if ( dir <= 0 || dir >= ROAR_DIR_DIRIDS ) {
444   ROAR_ERR("streams_set_dir(id=%i, dir=%i, defaults=%i) = -1 // error=INVAL", id, dir, defaults);
445   roar_err_set(ROAR_ERROR_INVAL);
446   return -1;
447  }
448
449  ROAR_DBG("streams_set_dir(*): g_config->streams[dir=%i].flags = 0x%.4x", dir, g_config->streams[dir].flags);
450
451  if ( streams_set_flag(id, g_config->streams[dir].flags) == -1 ) {
452   ROAR_WARN("streams_set_dir(*) = -1 // can not set stream flags");
453   return -1;
454  }
455
456   ss->mixer.scale   = g_config->streams[dir].mixer.scale;
457   ss->mixer.rpg_mul = g_config->streams[dir].mixer.rpg_mul;
458   ss->mixer.rpg_div = g_config->streams[dir].mixer.rpg_div;
459 }
460
461 if ( dir != ROAR_DIR_MIXING ) {
462  switch (streams_get_subsys(id)) {
463   case ROAR_SUBSYS_WAVEFORM:
464     streams_set_mixer_stream(id, g_waveform_mixer.stream);
465     roardsp_chanlist_init(ss->chanmap.in,  ROAR_STREAM(ss)->info.channels, ROARDSP_CHANLIST_MAP_ROARAUDIO);
466    break;
467#ifndef ROAR_WITHOUT_DCOMP_MIDI
468   case ROAR_SUBSYS_MIDI:
469     roardsp_chanlist_init(ss->chanmap.in,  ROAR_STREAM(ss)->info.channels, ROARDSP_CHANLIST_MAP_MIDI);
470     streams_set_mixer_stream(id, g_midi_mixer.stream);
471    break;
472#endif
473#ifndef ROAR_WITHOUT_DCOMP_LIGHT
474   case ROAR_SUBSYS_LIGHT:
475     streams_set_mixer_stream(id, g_light_mixer.stream);
476    break;
477#endif
478  }
479
480  if ( streams_get_ssdir(id) & STREAM_DIR_OUT ) {
481   if ( (mixer = streams_get_mixer_stream(id)) != -1 ) {
482    if ( g_streams[mixer]->flags & ROAR_FLAG_SINGLESINK ) {
483     streams_set_mixer_stream(id, -1);
484     return -1;
485    }
486   }
487  }
488
489  memcpy(ss->chanmap.out, ss->chanmap.in, sizeof(ss->chanmap.out));
490  streams_set_map(id, NULL, 0);
491 } else {
492  streams_set_mixer_stream(id, id);
493 }
494
495 ROAR_DBG("streams_set_dir(*) = 0");
496 return 0;
497}
498
499int streams_get_dir    (int id) {
500 struct roar_stream_server * ss;
501
502 _CHECK_SID(id);
503
504 if ( (ss = g_streams[id]) == NULL )
505  return -1;
506
507 return ROAR_STREAM(ss)->dir;
508}
509
510int streams_set_mixer_stream(int id, int mixer) {
511 struct roar_stream_server * ss;
512
513 _CHECK_SID(id);
514
515 if ( (ss = g_streams[id]) == NULL )
516  return -1;
517
518 ss->mixer_stream = mixer;
519
520 return 0;
521}
522
523int streams_get_mixer_stream(int id) {
524 struct roar_stream_server * ss;
525
526 _CHECK_SID(id);
527
528 if ( (ss = g_streams[id]) == NULL )
529  return -1;
530
531 return ss->mixer_stream;
532}
533
534static int streams_set_role_handle(int id) {
535   switch (streams_rolestack->action) {
536    case RS_ERROR: /* nothing to do */; break;
537    case RS_MIX:   /* nothing to do */; break;
538    case RS_KICK:  streams_delete(id);  break;
539    case RS_MUTE:  streams_set_flag(id, ROAR_FLAG_MUTE);  break;
540    case RS_PAUSE: streams_set_flag(id, ROAR_FLAG_PAUSE); break;
541   }
542 return 0;
543}
544
545int streams_set_role   (int id, int role) {
546 struct roar_stream_server * ss;
547 const struct rolestack * rs;
548 int old_role;
549 int i;
550
551 ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
552
553 _CHECK_SID(id);
554
555 if ( (ss = g_streams[id]) == NULL )
556  return -1;
557
558 old_role = ss->role;
559 ss->role = role;
560
561 ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
562
563 if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
564  return 0;
565
566 ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
567
568 if ( old_role == role )
569  return 0;
570
571 if ( old_role != role && old_role != -1 && role != -1 ) {
572  streams_set_role(id, -1);
573  streams_set_role(id, role);
574 }
575
576 ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
577
578 if ( ss->role != -1 && ss->role == streams_rolestack->role ) {
579  ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
580
581  streams_role_num--;
582  if ( streams_role_num == 0 ) {
583   streams_rolestack = rolestack_get_role(-1); // get default
584   for (i = 0; i < ROAR_STREAMS_MAX; i++) {
585    if ( (ss = g_streams[i]) == NULL )
586     continue;
587    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
588     continue;
589    if ( ss->role == -1 )
590     continue;
591    rs = rolestack_get_role(ss->role);
592    if ( rs->index > streams_rolestack->role ) {
593     streams_rolestack = rs;
594    }
595   }
596   for (i = 0; i < ROAR_STREAMS_MAX; i++) {
597    if ( (ss = g_streams[i]) == NULL )
598     continue;
599    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
600     continue;
601    if ( ss->role == streams_rolestack->role )
602     streams_role_num++;
603   }
604  }
605 } else if ( role != -1 ) {
606  ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
607
608  rs = rolestack_get_role(role);
609  ROAR_DBG("streams_set_role(id=%i, role=%i): rs->index=%i, streams_rolestack->index=%i", id, role, rs->index, streams_rolestack->index);
610  if ( rs->index == streams_rolestack->index ) {
611   ROAR_DBG("streams_set_role(id=%i, role=%i): rs->index=%i, streams_rolestack->index=%i", id, role, rs->index, streams_rolestack->index);
612   streams_role_num++;
613  } else if ( rs->index > streams_rolestack->index ) {
614   ROAR_DBG("streams_set_role(id=%i, role=%i): rs=%p{.index=%i, .action=%s}", id, role, rs, rs->index, rolestack_action2str(rs->action));
615   streams_role_num  = 1;
616   streams_rolestack = rs;
617   for (i = 0; i < ROAR_STREAMS_MAX; i++) {
618    if ( (ss = g_streams[i]) == NULL )
619     continue;
620    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
621     continue;
622    rs = rolestack_get_role(ss->role);
623    ROAR_DBG("streams_set_role(id=%i, role=%i): i=%i, rs->index=%i, streams_rolestack->index=%i", id, role, i, rs->index, streams_rolestack->index);
624    if ( rs->index < streams_rolestack->index )
625     streams_set_role_handle(i);
626   }
627  } else {
628   ROAR_DBG("streams_set_role(id=%i, role=%i): streams_rolestack->action=%s", id, role, rolestack_action2str(streams_rolestack->action));
629   streams_set_role_handle(id);
630  }
631 }
632
633 ROAR_DBG("streams_set_role(id=%i, role=%i) = 0", id, role);
634 return 0;
635}
636
637int streams_get_subsys (int id) {
638 struct roar_stream_server * ss;
639
640 _CHECK_SID(id);
641
642 if ( (ss = g_streams[id]) == NULL )
643  return -1;
644
645 if ( ROAR_STREAM(ss)->dir == ROAR_DIR_THRU )
646  return streams_get_subsys(ROAR_STREAM(ss)->pos_rel_id);
647
648 return streams_dir2subsys(ROAR_STREAM(ss)->dir);
649}
650
651int streams_dir2subsys (int dir) {
652 switch (dir) {
653  case ROAR_DIR_PLAY:
654  case ROAR_DIR_RECORD:
655  case ROAR_DIR_MONITOR:
656  case ROAR_DIR_FILTER:
657  case ROAR_DIR_OUTPUT:
658  case ROAR_DIR_BIDIR:
659  case ROAR_DIR_RECPLAY:
660    return ROAR_SUBSYS_WAVEFORM;
661   break;
662  case ROAR_DIR_MIDI_IN:
663  case ROAR_DIR_MIDI_OUT:
664    return ROAR_SUBSYS_MIDI;
665   break;
666  case ROAR_DIR_LIGHT_IN:
667  case ROAR_DIR_LIGHT_OUT:
668    return ROAR_SUBSYS_LIGHT;
669   break;
670  case ROAR_DIR_RAW_IN:
671  case ROAR_DIR_RAW_OUT:
672    return ROAR_SUBSYS_RAW;
673   break;
674  case ROAR_DIR_COMPLEX_IN:
675  case ROAR_DIR_COMPLEX_OUT:
676    return ROAR_SUBSYS_COMPLEX;
677   break;
678  case ROAR_DIR_MIXING:
679    return ROAR_SUBSYS_NONE;
680   break;
681 }
682
683 return -1;
684}
685
686int streams_get_ssdir  (int id) {
687 struct roar_stream_server * ss;
688
689 _CHECK_SID(id);
690
691 if ( (ss = g_streams[id]) == NULL )
692  return -1;
693
694 switch (ROAR_STREAM(ss)->dir) {
695  case ROAR_DIR_PLAY:
696  case ROAR_DIR_MIDI_IN:
697  case ROAR_DIR_LIGHT_IN:
698  case ROAR_DIR_RAW_IN:
699  case ROAR_DIR_COMPLEX_IN:
700    return STREAM_DIR_IN;
701   break;
702  case ROAR_DIR_RECORD:
703  case ROAR_DIR_MONITOR:
704  case ROAR_DIR_OUTPUT:
705  case ROAR_DIR_MIDI_OUT:
706  case ROAR_DIR_LIGHT_OUT:
707  case ROAR_DIR_RAW_OUT:
708  case ROAR_DIR_COMPLEX_OUT:
709    return STREAM_DIR_OUT;
710   break;
711  case ROAR_DIR_MIXING:
712    return STREAM_DIR_NONE;
713   break;
714  case ROAR_DIR_FILTER:
715  case ROAR_DIR_BIDIR:
716  case ROAR_DIR_RECPLAY:
717    return STREAM_DIR_BIDIR;
718   break;
719  case ROAR_DIR_THRU:
720    return streams_get_ssdir(ROAR_STREAM(ss)->pos_rel_id);
721   break;
722 }
723
724 return -1;
725}
726
727#define _err() streams_delete(id); return -1;
728int streams_new_virtual (int parent, struct roar_stream_server ** stream) {
729 struct roar_stream_server * parent_ss, * ss;
730 struct roar_stream        * parent_s , *  s;
731 int id = -1;
732 int client, dir;
733
734 if ( streams_get(parent, &parent_ss) == -1 )
735  return -1;
736
737 if ( (client = streams_get_client(parent)) == -1 )
738  return -1;
739
740 if ( (dir = streams_get_dir(parent)) == -1 )
741  return -1;
742
743 if ( (id = streams_new()) == -1 ) {
744  return -1;
745 }
746
747 if ( client_stream_add(client, id) == -1 ) {
748  _err();
749 }
750
751 if ( streams_get(id, &ss) == -1 ) {
752  _err();
753 }
754
755 if ( streams_set_dir(id, dir, 1) == -1 ) {
756  _err();
757 }
758
759 s        = ROAR_STREAM(       ss);
760 parent_s = ROAR_STREAM(parent_ss);
761
762 s->pos_rel_id = parent;
763
764 if ( streams_set_rawflag(id, ROAR_FLAG_VIRTUAL) == -1 ) {
765  _err();
766 }
767
768 if ( stream != NULL )
769  *stream = ss;
770
771 return id;
772}
773#undef _err
774
775int streams_set_fh     (int id, int fh) {
776 struct roar_stream_server * ss;
777 struct roar_stream        * s;
778 int dir;
779 int nonblock = 1;
780
781 _CHECK_SID(id);
782
783 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
784  return -1;
785
786 if ( ss->ready && !(s->fh == -1 && fh == -2) ) {
787  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = -1 // try to set fh for stream which is already ready", id, fh);
788  return -1;
789 }
790
791 dir = s->dir;
792
793 ROAR_DBG("streams_set_fh(id=%i, fh=%i): g_streams[id]->id=%i", id, fh, s->id);
794
795 s->fh = fh;
796
797 ROAR_DBG("streams_set_fh(id=%i, fh=%i): driverID=%i", id, fh, ss->driver_id);
798
799 if ( ss->driver_id == -1 && fh != -2 ) {
800#ifndef ROAR_TARGET_WIN32
801  roar_vio_open_fh(&(ss->vio), fh);
802#else
803  roar_vio_open_fh_socket(&(ss->vio), fh);
804#endif
805 }
806
807 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
808
809 switch (dir) {
810  case ROAR_DIR_THRU:
811  case ROAR_DIR_RAW_IN:
812  case ROAR_DIR_RAW_OUT:
813   break;
814  default:
815    if ( codecfilter_open(&(ss->codecfilter_inst), &(ss->codecfilter), NULL,
816                     s->info.codec, ss) == -1 ) {
817     streams_delete(id); // TODO: FIXME: is this correct? shoudn't we return -1 in any case here?
818     return -1;
819    }
820   break;
821 }
822
823 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
824
825 if ( fh == -2 ) {
826  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
827  if ( roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_GET_READ_FH, &fh) == -1 ) {
828   fh = -2;
829  } else {
830   ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
831   if ( fh < 0 ) {
832    fh = -2;
833   } else {
834    s->fh = fh;
835   }
836  }
837 }
838
839 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
840
841 if ( fh == -1 || fh == -2 ) { // yes, this is valid, indecats full vio!
842  ss->ready = 1;
843  //ROAR_INFO("streams_set_fh(id=%i, fh=%i): stream state: %s->new", ROAR_DBG_INFO_VERBOSE, id, fh, roar_streamstate2str(ss->state));
844  _streams_change_state(ss, ROAR_STREAMSTATE_NEW, "streams_set_fh");
845  return 0;
846 }
847
848 ROAR_DBG("streams_set_fh(id=%i, fh=%i) = ?", id, fh);
849
850 switch (dir) {
851  case ROAR_DIR_MONITOR:
852  case ROAR_DIR_RECORD:
853  case ROAR_DIR_OUTPUT:
854  case ROAR_DIR_MIDI_OUT:
855  case ROAR_DIR_LIGHT_OUT:
856  case ROAR_DIR_RAW_OUT:
857    ROAR_SHUTDOWN(fh, SHUT_RD);
858   break;
859 }
860
861 if ( dir >= ROAR_DIR_DIRIDS )
862  return -1;
863
864 if ( g_config->streams[dir].flags & ROAR_FLAG_SYNC ) {
865  switch (dir) {
866   case ROAR_DIR_BRIDGE:
867   case ROAR_DIR_MIDI_OUT:
868    break;
869   default:
870     nonblock = 0;
871    break;
872  }
873 }
874
875
876 if ( !nonblock ) {
877  ss->ready = 1;
878  //ROAR_INFO("streams_set_fh(id=%i, fh=%i): stream state: %s->new", ROAR_DBG_INFO_VERBOSE, id, fh, roar_streamstate2str(ss->state));
879  _streams_change_state(ss, ROAR_STREAMSTATE_NEW, "streams_set_fh");
880
881  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = 0", id, fh);
882  return 0;
883 } else {
884#ifndef ROAR_TARGET_WIN32
885  if ( roar_socket_nonblock(fh, ROAR_SOCKET_NONBLOCK) == -1 )
886   return -1;
887#endif
888
889  ss->ready = 1;
890  //ROAR_INFO("streams_set_fh(id=%i, fh=%i): stream state: %s->new", ROAR_DBG_INFO_VERBOSE, id, fh, roar_streamstate2str(ss->state));
891  _streams_change_state(ss, ROAR_STREAMSTATE_NEW, "streams_set_fh");
892
893  ROAR_DBG("streams_set_fh(id=%i, fh=%i) = 0", id, fh);
894  return 0;
895 }
896}
897
898int streams_get_fh     (int id) {
899 _CHECK_SID(id);
900
901 return ROAR_STREAM(g_streams[id])->fh;
902}
903
904int streams_set_null_io(int id) {
905 struct roar_stream_server * ss;
906 struct roar_stream        * s;
907
908 _CHECK_SID(id);
909
910 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
911  return -1;
912
913 s->fh = -1;
914
915 return 0;
916}
917
918int streams_get    (int id, struct roar_stream_server ** stream) {
919 _CHECK_SID(id);
920
921 *stream = g_streams[id];
922
923 return 0;
924}
925
926int streams_get_clientobj (int id, struct roar_stream        ** stream) {
927 _CHECK_SID(id);
928
929 *stream = ROAR_STREAM(g_streams[id]);
930
931 return 0;
932}
933
934int streams_set_socktype (int id, int socktype) {
935 _CHECK_SID(id);
936
937 g_streams[id]->socktype = socktype;
938
939 return 0;
940}
941
942int streams_get_socktype (int id) {
943 _CHECK_SID(id);
944
945 return g_streams[id]->socktype;
946}
947
948int streams_is_ready     (int id) {
949 _CHECK_SID(id);
950
951 return g_streams[id]->ready;
952}
953
954int streams_is_new       (int id) {
955 _CHECK_SID(id);
956
957 return g_streams[id]->ready;
958}
959
960int streams_set_primary (int id, int prim) {
961 _CHECK_SID(id);
962
963 g_streams[id]->primary = prim;
964
965 return 0;
966}
967
968int streams_mark_primary (int id) {
969 return streams_set_primary(id, 1);
970}
971
972int streams_set_sync     (int id, int sync) {
973 int fh = streams_get_fh(id);
974
975 ROAR_DBG("streams_set_sync(id=%i, sync=%i) = ?", id, sync);
976
977 _CHECK_SID(id);
978
979 if ( fh > -1 ) {
980  if ( roar_socket_nonblock(fh, sync ? ROAR_SOCKET_BLOCK : ROAR_SOCKET_NONBLOCK) == -1 )
981   return -1;
982
983#ifdef ROAR_FDATASYNC
984  ROAR_FDATASYNC(fh);
985#endif
986
987  return 0;
988 } else {
989  return roar_vio_nonblock(&(g_streams[id]->vio), sync);
990 }
991}
992
993int streams_set_mmap (int id, int reset) {
994 int use = !reset;
995
996 _CHECK_SID(id);
997
998 return roar_vio_ctl(&(g_streams[id]->vio), ROAR_VIO_CTL_SET_UMMAP, &use);
999}
1000
1001int streams_set_single_sink(int id, int reset) {
1002 struct roar_stream_server * self_ss, * ss;
1003 struct roar_stream                   *  s;
1004 int mixer;
1005 size_t count = 0;
1006 int i;
1007 int ssdir;
1008
1009 /* FIXME: This code only uses one refc for the mixer shared with the inputs.
1010  *        If the flag is unset on the mixer but got set by the sources the counter
1011  *        may/will become corrupted.
1012  */
1013
1014 _CHECK_SID(id);
1015
1016 self_ss = g_streams[id];
1017
1018 mixer = self_ss->mixer_stream;
1019
1020 ROAR_DBG("streams_set_single_sink(id=%i, reset=%i): mixer=%i", id, reset, mixer);
1021
1022 if ( !reset && id != mixer )
1023  if ( self_ss->flags & ROAR_FLAG_SINGLESINK )
1024   return 0;
1025
1026 if ( id == mixer ) {
1027  if ( reset ) {
1028   if ( self_ss->single_sink_self_c ) {
1029    ROAR_DBG("streams_set_single_sink(id=%i, reset=%i): mixer=%i", id, reset, mixer);
1030    self_ss->single_sink_self_c--;
1031    self_ss->single_sink_c--;
1032    if ( self_ss->single_sink_c == 0 ) {
1033     ROAR_DBG("streams_set_single_sink(id=%i, reset=%i): mixer=%i", id, reset, mixer);
1034     self_ss->flags |= ROAR_FLAG_SINGLESINK;
1035     self_ss->flags -= ROAR_FLAG_SINGLESINK;
1036    }
1037    return 0;
1038   } else {
1039    return -1;
1040   }
1041  } else {
1042   if ( self_ss->single_sink_c ) {
1043    self_ss->single_sink_self_c++;
1044    self_ss->single_sink_c++;
1045    return 0;
1046   }
1047  }
1048 } else if ( reset ) {
1049  ROAR_DBG("streams_set_single_sink(id=%i, reset=%i): mixer=%i", id, reset, mixer);
1050
1051  if ( (ss = g_streams[mixer]) == NULL )
1052   return -1;
1053
1054  if ( ss->single_sink_c == 0 )
1055   return -1;
1056  ss->single_sink_c--;
1057
1058  if ( ss->single_sink_c == 0 ) {
1059    self_ss->flags |= ROAR_FLAG_SINGLESINK;
1060    self_ss->flags -= ROAR_FLAG_SINGLESINK;
1061         ss->flags |= ROAR_FLAG_SINGLESINK;
1062         ss->flags -= ROAR_FLAG_SINGLESINK;
1063  }
1064
1065  return 0;
1066 }
1067
1068
1069
1070 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1071  if ( (s = ROAR_STREAM((ss = g_streams[i]))) != NULL ) {
1072   if ( s->dir == ROAR_DIR_THRU )
1073    if ( s->pos_rel_id == id || s->pos_rel_id == mixer || g_streams[s->pos_rel_id]->mixer_stream == mixer )
1074     return -1;
1075
1076   if ( ss->mixer_stream != mixer )
1077    continue;
1078
1079   ssdir = streams_get_ssdir(i);
1080
1081   if ( ssdir & STREAM_DIR_OUT )
1082    count++;
1083  }
1084 }
1085
1086 if ( count > 1 )
1087  return -1;
1088
1089 ss = g_streams[mixer];
1090
1091 if ( id == mixer )
1092  ss->single_sink_self_c++;
1093
1094 ss->single_sink_c++;
1095
1096 self_ss->flags |= ROAR_FLAG_SINGLESINK;
1097      ss->flags |= ROAR_FLAG_SINGLESINK;
1098
1099 return 0;
1100}
1101
1102int streams_set_flag     (int id, uint32_t flag) {
1103 int parent;
1104 int tmp;
1105
1106 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1107
1108 _CHECK_SID(id);
1109
1110 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1111
1112 if ( flag & ROAR_FLAG_IMMUTABLE )
1113  flag |= ROAR_FLAG_PRIMARY;
1114
1115
1116 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1117
1118 // check if flags we are going to change are protected:
1119 if ( g_streams[id]->flags_protection & flag )
1120  return -1;
1121
1122 flag |= g_streams[id]->flags;
1123 flag -= g_streams[id]->flags;
1124
1125 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1126
1127 if ( flag & ROAR_FLAG_MMAP ) {
1128  if ( streams_set_mmap(id, 0) == -1 ) {
1129   flag -= ROAR_FLAG_MMAP;
1130   return -1;
1131  }
1132 }
1133
1134 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1135
1136 if ( flag & ROAR_FLAG_PRIMARY ) {
1137  streams_set_primary(id, 1);
1138  flag -= ROAR_FLAG_PRIMARY;
1139 }
1140
1141 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1142
1143 if ( flag & ROAR_FLAG_SINGLESINK ) {
1144  if ( streams_set_single_sink(id, 0) == -1 ) {
1145   return -1;
1146  }
1147  flag -= ROAR_FLAG_SINGLESINK;
1148 }
1149
1150 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1151
1152 if ( flag & ROAR_FLAG_VIRTUAL ) {
1153  if ( (parent = ROAR_STREAM(g_streams[id])->pos_rel_id) == -1 )
1154   return -1;
1155
1156  if ( streams_ctl(parent, ROAR_CODECFILTER_CTL_VIRTUAL_NEW|ROAR_STREAM_CTL_TYPE_INT, &id) == -1 ) {
1157//   flag -= ROAR_FLAG_VIRTUAL;
1158   return -1;
1159  }
1160
1161  if ( client_stream_move(streams_get_client(parent), id) == -1 ) {
1162   return -1;
1163  }
1164 }
1165
1166 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1167
1168 if ( flag & ROAR_FLAG_SYNC ) {
1169  ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1170  switch (ROAR_STREAM(g_streams[id])->dir) {
1171   // for this stream types the flag is used in the subsystem:
1172   case ROAR_DIR_BRIDGE:
1173   case ROAR_DIR_MIDI_OUT:
1174    break;
1175
1176   // normal behavor (vio blocking):
1177   default:
1178     ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1179     // the fh is updated as soon as the fh get ready in case the default ask to set sync
1180     if ( g_streams[id]->ready || (!g_streams[id]->ready && !(g_config->streams[ROAR_STREAM(g_streams[id])->dir].flags & ROAR_FLAG_SYNC)) ) {
1181      ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1182      if ( streams_set_sync(id, 1) == -1 ) {
1183       ROAR_WARN("streams_set_flag(id=%i, flag=0x%.8X): Can not set SYNC flag.", id, flag);
1184       flag -= ROAR_FLAG_SYNC;
1185      }
1186     }
1187    break;
1188  }
1189  ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1190
1191  if ( flag & ROAR_FLAG_SYNC ) {
1192   g_streams[id]->flags |= ROAR_FLAG_SYNC;
1193   streams_change_sync_num(id, +1);
1194  }
1195 }
1196
1197 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1198
1199 if ( flag & ROAR_FLAG_HWMIXER ) { // currently not supported -> ignored
1200  g_streams[id]->flags |= flag;
1201  if ( streams_set_mixer(id) == -1 ) {
1202   g_streams[id]->flags -= flag;
1203   return -1;
1204  }
1205 }
1206
1207 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1208
1209 if ( flag & ROAR_FLAG_RECSOURCE ) {
1210  if ( streams_recsource_id != -1 ) {
1211   if ( streams_reset_flag(streams_recsource_id, ROAR_FLAG_RECSOURCE) == -1 )
1212    return -1;
1213  }
1214
1215  if ( g_streams[id]->ready ) {
1216   tmp = 1;
1217   if ( stream_vio_ctl(id, ROAR_VIO_CTL_SET_RECORD, &tmp) == -1 )
1218    return -1;
1219  }
1220
1221  streams_recsource_id = id;
1222 }
1223
1224 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1225
1226 g_streams[id]->flags |= flag;
1227
1228#ifdef ROAR_SUPPORT_META
1229 if ( flag & ROAR_FLAG_META )
1230  stream_meta_finalize(id);
1231#endif
1232
1233 ROAR_DBG("streams_set_flag(id=%i, flag=0x%.8X) = 0", id, flag);
1234
1235 return 0;
1236}
1237
1238int streams_set_rawflag  (int id, uint32_t flag) {
1239 _CHECK_SID(id);
1240
1241 g_streams[id]->flags |= flag;
1242
1243 if ( flag & ROAR_FLAG_SYNC )
1244  streams_change_sync_num(id, +1);
1245
1246 return 0;
1247}
1248
1249int streams_reset_flag   (int id, uint32_t flag) {
1250 int tmp;
1251
1252 ROAR_DBG("streams_reset_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1253
1254 _CHECK_SID(id);
1255
1256 // check if flags we are going to change are protected:
1257 if ( g_streams[id]->flags_protection & flag )
1258  return -1;
1259
1260 if ( g_streams[id]->flags & ROAR_FLAG_IMMUTABLE ) {
1261  flag |= ROAR_FLAG_PRIMARY;
1262  flag -= ROAR_FLAG_PRIMARY;
1263 }
1264
1265 flag &= g_streams[id]->flags;
1266
1267 ROAR_DBG("streams_reset_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1268
1269 if ( (flag & ROAR_FLAG_RECSOURCE) && streams_recsource_id == id ) {
1270  if ( g_streams[id]->ready ) {
1271   tmp = 0;
1272   if ( stream_vio_ctl(id, ROAR_VIO_CTL_SET_RECORD, &tmp) == -1 ) {
1273    if ( alive ) { // do not warn if we are shutting down anyway.
1274     ROAR_WARN("streams_reset_flag(id=%i, flag=0x%.8X): Driver refused to reset record flag.", id, flag);
1275    }
1276    ROAR_DBG("streams_reset_flag(id=%i, flag=0x%.8X) = -1", id, flag);
1277    return -1;
1278   }
1279  }
1280
1281  streams_recsource_id = -1;
1282 }
1283
1284 ROAR_DBG("streams_reset_flag(id=%i, flag=0x%.8X) = ?", id, flag);
1285
1286
1287 if ( flag & ROAR_FLAG_MMAP ) {
1288  if ( streams_set_mmap(id, 1) == -1 ) {
1289   flag -= ROAR_FLAG_MMAP;
1290   return -1;
1291  }
1292 }
1293
1294 if ( flag & ROAR_FLAG_PRIMARY ) {
1295  streams_set_primary(id, 0);
1296  flag -= ROAR_FLAG_PRIMARY;
1297 }
1298
1299 if ( flag & ROAR_FLAG_SINGLESINK ) {
1300  if ( streams_set_single_sink(id, 1) == -1 ) {
1301   return -1;
1302  }
1303  flag -= ROAR_FLAG_SINGLESINK;
1304 }
1305
1306 if ( flag & ROAR_FLAG_SYNC ) {
1307  // we refuse to reset the flag on FILTER streams
1308  if ( streams_get_dir(id) == ROAR_DIR_FILTER ) {
1309//   flags -= ROAR_FLAG_SYNC;
1310   return -1;
1311  } else {
1312   if ( streams_set_sync(id, 0) == -1 )
1313    return -1;
1314
1315   g_streams[id]->flags |= ROAR_FLAG_SYNC;
1316   g_streams[id]->flags -= ROAR_FLAG_SYNC;
1317   flag -= ROAR_FLAG_SYNC;
1318   streams_change_sync_num(id, -1);
1319  }
1320 }
1321
1322 g_streams[id]->flags |= flag;
1323 g_streams[id]->flags -= flag;
1324
1325 ROAR_DBG("streams_reset_flag(id=%i, flag=0x%.8X) = 0", id, flag);
1326
1327 return 0;
1328}
1329
1330int streams_get_flag     (int id, uint32_t flag) {
1331 _CHECK_SID(id);
1332
1333 return g_streams[id]->flags & flag ? 1 : 0;
1334}
1335
1336int streams_protect_flag (int id, uint32_t flag) {
1337 _CHECK_SID(id);
1338
1339 g_streams[id]->flags_protection |= flag;
1340
1341 return 0;
1342}
1343
1344int streams_set_name     (int id, char * name) {
1345 char * str;
1346
1347 _CHECK_SID(id);
1348
1349 if ( (str = roar_mm_strdup(name)) == NULL )
1350  return -1;
1351
1352 if ( g_streams[id]->name != NULL )
1353  roar_mm_free(g_streams[id]->name);
1354
1355 g_streams[id]->name = str;
1356
1357 return 0;
1358}
1359
1360char * streams_get_name  (int id) {
1361 _CHECK_SID_RET(id, NULL);
1362
1363 return g_streams[id]->name;
1364}
1365
1366
1367int streams_calc_delay    (int id) {
1368 struct roar_stream_server * ss;
1369 struct roar_stream        * s;
1370 register uint_least32_t d = 0;
1371 uint_least32_t t[1];
1372 uint64_t       tmp;
1373
1374 _CHECK_SID(id);
1375
1376 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
1377  return -1;
1378
1379 // mixer store there value in ss->delay directly
1380 if ( s->dir == ROAR_DIR_MIXING )
1381  return 0;
1382
1383#if 0
1384 // this only confuses the user...
1385 if ( ss->mixer_stream != id ) {
1386  if ( streams_calc_delay(ss->mixer_stream) != -1 ) {
1387   d += g_streams[ss->mixer_stream]->delay; // in case we can calc the delay
1388                                            // the stream must exist, so no check here
1389  }
1390 }
1391#endif
1392
1393 if ( ss->codecfilter != -1 ) {
1394  if ( codecfilter_delay(ss->codecfilter_inst, ss->codecfilter, t) != -1 )
1395   d += *t;
1396 }
1397
1398 if ( ss->vio.ctl != NULL ) {
1399  if ( roar_vio_ctl(&(ss->vio), ROAR_VIO_CTL_GET_DELAY, t) != -1 ) { // *t is in byte
1400   ROAR_DBG("streams_calc_delay(id=%i): VIO delay in byte: %i", id, *t);
1401   tmp = *t;
1402   tmp *= 1000000; // musec per sec
1403   tmp /= s->info.rate * s->info.channels * (s->info.bits/8);
1404   ROAR_DBG("streams_calc_delay(id=%i): VIO delay in musec: %llu", id, tmp);
1405
1406   d += tmp;
1407  }
1408 }
1409
1410 ROAR_DBG("streams_calc_delay(id=%i): delay in musec: %i", id, d);
1411
1412 ss->delay = d;
1413
1414 return 0;
1415}
1416
1417int streams_set_mixer    (int id) {
1418 struct roar_stream_server * ss;
1419 struct roar_stream_server * pmss;
1420 int i;
1421 int subsys;
1422 int tsubsys;
1423
1424 _CHECK_SID(id);
1425
1426 if ( (ss = g_streams[id]) == NULL )
1427  return -1;
1428
1429 if ( streams_get_flag(id, ROAR_FLAG_PASSMIXER) == 1 ) {
1430  if ( (subsys = streams_get_subsys(id)) == -1 )
1431   return -1;
1432
1433  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1434   if ( (pmss = g_streams[i]) != NULL ) {
1435    if ( streams_get_flag(i, ROAR_FLAG_PASSMIXER) == 1 ) {
1436     tsubsys = streams_get_subsys(i);
1437     if ( tsubsys == subsys || tsubsys == ROAR_SUBSYS_NONE ) {
1438      if ( &(pmss->mixer) != &(ss->mixer) ) {
1439       if ( roar_conv_volume(&(pmss->mixer), &(ss->mixer),
1440                             ROAR_STREAM(pmss)->info.channels, ROAR_STREAM(ss)->info.channels) == -1 ) {
1441        ROAR_WARN("streams_set_mixer(id=%i): Can not convert mixer settings for stream %i", id, i);
1442       }
1443      }
1444
1445      // update hwmixers and the like but do not set mixer value recrusivly.
1446      streams_reset_flag(i, ROAR_FLAG_PASSMIXER);
1447      streams_set_mixer(i);
1448      streams_set_flag(i, ROAR_FLAG_PASSMIXER);
1449     }
1450    }
1451   }
1452  }
1453 }
1454
1455 roar_notify_core_emit_snoargs(ROAR_OE_STREAM_CHANGE_VOLUME, -1, id, ROAR_OT_STREAM);
1456
1457 if ( !streams_get_flag(id, ROAR_FLAG_HWMIXER) )
1458  return 0;
1459
1460 if ( ss->driver_id != -1 ) {
1461  return driver_set_volume(id, &(ss->mixer));
1462#ifndef ROAR_WITHOUT_DCOMP_MIXER
1463 } else if ( ss->mixerstream != NULL ) {
1464  return hwmixer_set_volume(id, ss, ss->mixerstream, &(ss->mixer));
1465#endif
1466 } else {
1467  return 0;
1468 }
1469}
1470
1471int streams_set_map      (int id, char * map, size_t len) {
1472 struct roar_stream_server * ss;
1473 int ssdir;
1474
1475 _CHECK_SID(id);
1476
1477 if ( (ss = g_streams[id]) == NULL )
1478  return -1;
1479
1480 if ( map != NULL ) {
1481  if ( ROAR_STREAM(ss)->info.channels != len )
1482   return -1;
1483 }
1484
1485 ssdir = streams_get_ssdir(id);
1486
1487 switch (ssdir) {
1488  case STREAM_DIR_IN:
1489  case STREAM_DIR_NONE:
1490    memset(ss->chanmap.in, 0, sizeof(ss->chanmap.in));
1491
1492    if ( map != NULL )
1493     memcpy(ss->chanmap.in, map, len);
1494
1495    roardsp_chanmap_calc(&(ss->chanmap), ROARDSP_CHANMAP_MAP, 0);
1496   break;
1497  case STREAM_DIR_OUT:
1498    memset(ss->chanmap.out, 0, sizeof(ss->chanmap.out));
1499
1500    if ( map != NULL )
1501     memcpy(ss->chanmap.out, map, len);
1502
1503    roardsp_chanmap_calc(&(ss->chanmap), ROARDSP_CHANMAP_MAP, 0);
1504   break;
1505  default:
1506    return -1;
1507 }
1508
1509 return 0;
1510}
1511
1512int streams_get_rpg      (int id, struct roar_stream_rpg * rpg) {
1513 _CHECK_SID(id);
1514
1515 if ( rpg == NULL ) {
1516  roar_err_set(ROAR_ERROR_FAULT);
1517  return -1;
1518 }
1519
1520 rpg->mode = g_streams[id]->rpgmode;
1521 rpg->mul  = g_streams[id]->mixer.rpg_mul;
1522 rpg->div  = g_streams[id]->mixer.rpg_div;
1523
1524 if ( rpg->mode == ROAR_RPGMODE_DEFAULT )
1525  rpg->mode = g_config->streams[ROAR_STREAM(g_streams[id])->dir].rpgmode;
1526
1527 return 0;
1528}
1529
1530int streams_set_rpg      (int id, const struct roar_stream_rpg * rpg) {
1531 int mode;
1532
1533 _CHECK_SID(id);
1534
1535 if ( rpg == NULL ) {
1536  roar_err_set(ROAR_ERROR_FAULT);
1537  return -1;
1538 }
1539
1540 // test if we have a valid value at all.
1541 if ( rpg->mode > ROAR_RPGMODE_TRACKALBUM || rpg->mode < ROAR_RPGMODE_DEFAULT ) {
1542  roar_err_set(ROAR_ERROR_RANGE);
1543  return -1;
1544 }
1545
1546 mode = g_streams[id]->rpgmode = rpg->mode;
1547
1548 if ( mode == ROAR_RPGMODE_DEFAULT )
1549  mode = g_config->streams[ROAR_STREAM(g_streams[id])->dir].rpgmode;
1550
1551 switch (mode) {
1552  case ROAR_RPGMODE_NONE:
1553    g_streams[id]->mixer.rpg_mul = 1;
1554    g_streams[id]->mixer.rpg_div = 1;
1555   break;
1556  case ROAR_RPGMODE_USER:
1557    g_streams[id]->mixer.rpg_mul = rpg->mul;
1558    g_streams[id]->mixer.rpg_div = rpg->div;
1559   break;
1560 }
1561
1562 return 0;
1563}
1564
1565
1566int streams_ltm_ctl      (int id, int mt, int window, int cmd) {
1567 struct roar_stream_server * ss;
1568 struct roar_stream_ltm *    ltm;
1569 int i;
1570
1571 _CHECK_SID(id);
1572
1573 // currently we only support the WORKBLOCK window
1574 if ( window != ROAR_LTM_WIN_WORKBLOCK )
1575  return -1;
1576
1577 // currently we only support ROAR_LTM_MT_RMS
1578 if ( (mt | ROAR_LTM_MT_RMS) - ROAR_LTM_MT_RMS )
1579  return -1;
1580
1581 if ( (ss = g_streams[id]) == NULL )
1582  return -1;
1583
1584 switch (cmd) {
1585  case ROAR_LTM_SST_NOOP:
1586    return 0;
1587   break;
1588  case ROAR_LTM_SST_REGISTER:
1589    // test if the window is already registered:
1590    for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1591     ltm = &(ss->ltm[i]);
1592     if ( ltm->refc && ltm->window == window ) {
1593      ltm->refc++;
1594      ltm->mt |= mt;
1595      return 0;
1596     }
1597    }
1598
1599    // register
1600    for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1601     ltm = &(ss->ltm[i]);
1602     if ( ltm->refc == 0 ) {
1603      memset(ltm, 0, sizeof(struct roar_stream_ltm));
1604      ltm->refc = 1;
1605      ltm->window = window;
1606      ltm->parent_window = -1;
1607      ltm->mt = mt;
1608      ltm->channels = ROAR_STREAM(ss)->info.channels;
1609      if ( (ltm->cur = roar_mm_malloc(ltm->channels*sizeof(struct roar_ltm_vals))) == NULL ) {
1610       ltm->refc = 0; // reset
1611       return -1;
1612      }
1613      memset(ltm->cur, 0, ltm->channels*sizeof(struct roar_ltm_vals));
1614      return 0;
1615     }
1616    }
1617    return -1;
1618   break;
1619  case ROAR_LTM_SST_UNREGISTER:
1620    for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1621     ltm = &(ss->ltm[i]);
1622     if ( ltm->refc && ltm->window == window ) {
1623      ltm->refc--;
1624      if ( ! ltm->refc ) {
1625       roar_mm_free(ltm->cur);
1626       return 0;
1627      }
1628     }
1629    }
1630    return -1;
1631   break;
1632  default:
1633    return -1;
1634   break;
1635 }
1636}
1637
1638int streams_ltm_calc     (int id, struct roar_audio_info * info, void * data, size_t len) {
1639 struct roar_stream_server * ss;
1640 struct roar_stream_ltm *    ltm = NULL;
1641 int64_t rmsbuf_real[8];
1642 int64_t * rmsbuf = rmsbuf_real;
1643 size_t samples = 0;
1644 int i;
1645
1646 _CHECK_SID(id);
1647
1648 if ( data == NULL || info == NULL )
1649  return -1;
1650
1651 if ( info->codec != ROAR_CODEC_DEFAULT )
1652  return -1;
1653
1654 if ( (ss = g_streams[id]) == NULL )
1655  return -1;
1656
1657 for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1658  if ( ss->ltm[i].refc && ss->ltm[i].window == ROAR_LTM_WIN_WORKBLOCK ) {
1659   ltm = &(ss->ltm[i]);
1660   break;
1661  }
1662 }
1663
1664 if ( ltm == NULL )
1665  return -1;
1666
1667 // TODO: support change of number of channels
1668 if ( ltm->channels != info->channels )
1669  return -1;
1670
1671 if ( len == 0 ) {
1672  memset(ltm->cur, 0, ltm->channels * sizeof(struct roar_ltm_vals));
1673  return 0;
1674 }
1675
1676 // TODO: support more channels then rmsbuf_real has space for
1677 if ( ltm->channels > (sizeof(rmsbuf_real)/sizeof(*rmsbuf_real)) ) {
1678  return -1;
1679 }
1680
1681 samples = len / info->bits;
1682
1683 if ( ltm->mt & ROAR_LTM_MT_RMS ) {
1684  if ( roar_rms2_1_b_n(data, samples, rmsbuf, ltm->channels, info->bits) == -1 )
1685   return -1;
1686
1687  for (i = 0; i < ltm->channels; i++) {
1688   ltm->cur[i].rms = rmsbuf[i] << (64 - info->bits*2);
1689  }
1690
1691  ROAR_DBG("streams_ltm_calc(id=%i,...): rmsbuf[0]=%lli", id, (long long int)rmsbuf[0]);
1692 }
1693
1694 return 0;
1695}
1696
1697struct roar_stream_ltm * streams_ltm_get(int id, int mt, int window) {
1698 struct roar_stream_server * ss;
1699 struct roar_stream_ltm *    ltm = NULL;
1700 int i;
1701
1702 _CHECK_SID_RET(id, NULL);
1703
1704 if ( (ss = g_streams[id]) == NULL )
1705  return NULL;
1706
1707 for (i = 0; i < MAX_LTM_WINDOWS_PER_STREAM; i++) {
1708  if ( ss->ltm[i].refc && ss->ltm[i].window == window ) {
1709   ltm = &(ss->ltm[i]);
1710   break;
1711  }
1712 }
1713
1714 if ( ltm == NULL )
1715  return NULL;
1716
1717 if ( (ltm->mt & mt) != mt )
1718  return NULL;
1719
1720 return ltm;
1721}
1722
1723#ifndef ROAR_WITHOUT_DCOMP_MIXER
1724struct hwmixer_stream * streams_get_mixerstream(int id) {
1725 _CHECK_SID_RET(id, NULL);
1726
1727 return g_streams[id]->mixerstream;
1728}
1729
1730int streams_set_mixerstream(int id, struct hwmixer_stream * mstream) {
1731 _CHECK_SID(id);
1732
1733 g_streams[id]->mixerstream = mstream;
1734
1735 return 0;
1736}
1737
1738int streams_read_mixervalues(int id) {
1739 struct roar_stream_server * ss;
1740
1741 _CHECK_SID(id);
1742
1743 if ( (ss = g_streams[id]) == NULL )
1744  return -1;
1745
1746 if ( ss->mixerstream == NULL )
1747  return -1;
1748
1749 return hwmixer_get_volume(id, ss, ss->mixerstream, &(ss->mixer));
1750}
1751#endif
1752
1753int streams_ctl          (int id, int_least32_t cmd, void * data) {
1754 struct roar_stream_server * ss;
1755 int_least32_t comp;
1756
1757 _CHECK_SID(id);
1758
1759 if ( (ss = g_streams[id]) == NULL )
1760  return -1;
1761
1762 comp = cmd & ROAR_STREAM_CTL_COMPMASK;
1763
1764 cmd &= ~comp;
1765
1766 ROAR_DBG("streams_ctl(id=%i, cmd=?, data=%p): comp=0x%.8x, cmd=0x%.4x", id, data, comp, cmd);
1767
1768 switch (comp) {
1769  case ROAR_STREAM_CTL_COMP_BASE:
1770   break;
1771  case ROAR_STREAM_CTL_COMP_CF:
1772    return codecfilter_ctl(ss->codecfilter_inst, ss->codecfilter, cmd, data);
1773   break;
1774  case ROAR_STREAM_CTL_COMP_DRV:
1775   break;
1776  default:
1777   return -1;
1778 }
1779
1780 return -1;
1781}
1782
1783int streams_get_outputbuffer  (int id, void ** buffer, size_t size) {
1784 _CHECK_SID(id);
1785
1786 // output buffer size does never change.
1787 if ( g_streams[id]->output != NULL ) {
1788  *buffer = g_streams[id]->output;
1789  return 0;
1790 }
1791
1792 if ( (g_streams[id]->output = roar_mm_malloc(size)) == NULL ) {
1793  ROAR_ERR("streams_get_outputbuffer(*): Can not alloc: %s", strerror(errno));
1794  return -1;
1795 }
1796
1797 *buffer = g_streams[id]->output;
1798
1799 return 0;
1800}
1801
1802int streams_fill_mixbuffer2 (int id, struct roar_audio_info * info) {
1803 size_t   outlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(info);
1804 void   * outdata;
1805 size_t   inlen;
1806 size_t   inlen_got;
1807 void   * indata = NULL;
1808 size_t   buflen;
1809 void   * bufdata = NULL;
1810 struct roar_buffer * bufbuf = NULL;
1811 int      is_the_same = 0;
1812 struct roar_audio_info    * stream_info;
1813 struct roar_stream        * s;
1814 struct roar_stream_server * ss;
1815
1816 _CHECK_SID(id);
1817
1818 if ( (s = ROAR_STREAM(ss = g_streams[id])) == NULL )
1819  return -1;
1820
1821 // set up stream_info
1822 stream_info = &(s->info);
1823
1824 // calc todo_in
1825 inlen = ROAR_OUTPUT_CALC_OUTBUFSIZE(stream_info);
1826
1827 buflen = ROAR_OUTPUT_CALC_OUTBUFSIZE_MAX(info, stream_info);
1828
1829 ROAR_DBG("streams_fill_mixbuffer2(id=%i, info=%p{...}): inlen=%lu, buflen=%lu", id, info, (unsigned long)inlen, (unsigned long)buflen);
1830
1831 if ( inlen == 0 ) {
1832  ROAR_WARN("streams_fill_mixbuffer2(id=%i, info=%p{...}): inlen == 0, this should not happen!", id, info);
1833  return -1;
1834 }
1835
1836 if ( streams_get_outputbuffer(id, &outdata, outlen) == -1 ) {
1837  return -1;
1838 }
1839
1840 if ( outdata == NULL ) {
1841  return -1;
1842 }
1843
1844 ROAR_DBG("streams_fill_mixbuffer2(*): outdata=%p, len=%i->%i (in->out)", outdata, inlen, outlen);
1845
1846 is_the_same = stream_info->rate     == info->rate     && stream_info->bits  == info->bits &&
1847               stream_info->channels == info->channels && stream_info->codec == info->codec;
1848
1849 ROAR_DBG("streams_fill_mixbuffer2(*): is_the_same=%i", is_the_same);
1850
1851 if ( !is_the_same && buflen > outlen ) {
1852/*
1853  // this is not supported at the moment
1854  memset(outdata, 0, outlen);
1855  return -1;
1856*/
1857
1858  if ( roar_buffer_new(&bufbuf, buflen) == -1 )
1859   return -1;
1860
1861  if ( roar_buffer_get_data(bufbuf, &bufdata) == -1 )
1862   return -1;
1863  indata  = bufdata;
1864 } else {
1865  indata  = outdata;
1866  bufdata = outdata;
1867 }
1868
1869 inlen_got = inlen;
1870
1871 ROAR_DBG("streams_fill_mixbuffer2(id=%i, info=...): inlen_got=%u", id, inlen_got);
1872
1873 if ( stream_shift_out_buffer(id, indata, &inlen_got) == -1 ) {
1874  if ( ss->is_new ) {
1875   ss->pre_underruns++;
1876   roar_notify_core_emit_simple(ROAR_OE_STREAM_XRUN, -1, id, ROAR_OT_STREAM, ROAR_XRUN_UNDER_PRE, ss->pre_underruns, NULL, 0);
1877  } else {
1878   ROAR_WARN("streams_fill_mixbuffer2(id=%i, info=...): underrun in stream", id);
1879   ss->post_underruns++;
1880   roar_notify_core_emit_simple(ROAR_OE_STREAM_XRUN, -1, id, ROAR_OT_STREAM, ROAR_XRUN_UNDER_POST, ss->post_underruns, NULL, 0);
1881  }
1882  memset(outdata, 0, outlen);
1883  return 0;
1884 }
1885
1886 ROAR_DBG("streams_fill_mixbuffer2(id=%i, info=...): inlen_got=%u", id, inlen_got);
1887
1888 if ( ss->is_new ) {
1889  //ROAR_INFO("streams_fill_mixbuffer2(id=%i, info=...): stream state: new->old", ROAR_DBG_INFO_VERBOSE, id);
1890  _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_fill_mixbuffer2");
1891 }
1892
1893 ss->is_new = 0;
1894
1895 // check channel map:
1896#if 0
1897 if ( roardsp_chanmap_mappcm(indata, indata, inlen, stream_info->channels, &(ss->chanmap), stream_info->bits) == -1 ) {
1898  if ( bufbuf != NULL )
1899   roar_buffer_free(bufbuf);
1900  return -1;
1901 }
1902#endif
1903
1904 // TODO: this only works in case a we have a amp for the given stream parameters.
1905 if ( !streams_get_flag(id, ROAR_FLAG_HWMIXER) && !streams_get_flag(id, ROAR_FLAG_PASSMIXER) ) {
1906  ROAR_DBG("streams_fill_mixbuffer2(*): CALL roar_amp_pcm(*)...");
1907  if ( roar_amp_pcm(indata, stream_info->bits, indata, 8*inlen / stream_info->bits, stream_info->channels, &(ss->mixer)) == -1 )
1908   return -1;
1909 }
1910
1911 // check codec, bits, channels, rate...
1912 if ( is_the_same ) {
1913  if ( indata != outdata )
1914   memcpy(outdata, indata, inlen);
1915
1916  if ( inlen < outlen )
1917   memset(outdata+inlen, 0, outlen-inlen);
1918 } else {
1919//  if ( roar_conv(outdata, indata, (8*inlen_got*info->rate)/(stream_info->rate * stream_info->bits), stream_info, info) == -1 ) {
1920  ROAR_DBG("streams_fill_mixbuffer2(*): CALL roar_conv2(*)...");
1921  if ( roar_conv2(bufdata, indata, inlen, stream_info, info, outlen) == -1 ) {
1922   if ( bufbuf != NULL )
1923    roar_buffer_free(bufbuf);
1924   return -1;
1925  }
1926
1927//  memset(outdata, 0, outlen);
1928 }
1929
1930 if ( bufbuf != NULL ) {
1931  memcpy(outdata, bufdata, outlen);
1932  roar_buffer_free(bufbuf);
1933 }
1934
1935 streams_ltm_calc(id, stream_info, outdata, outlen);
1936
1937 if ( streams_get_flag(id, ROAR_FLAG_ANTIECHO) ) {
1938  ROAR_DBG("streams_fill_mixbuffer2(*): Calcing antiecho...");
1939  // we can ignore errors here:
1940  if ( stream_outputbuffer_request(id, &bufbuf, buflen) == 0 ) {
1941   if ( roar_buffer_get_data(bufbuf, &bufdata) != -1 )
1942    memcpy(bufdata, outdata, outlen);
1943  }
1944 }
1945
1946 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);
1947 s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, (inlen_got*8)/stream_info->bits);
1948
1949 ROAR_DBG("streams_fill_mixbuffer2(*) = 0");
1950 return 0;
1951}
1952
1953
1954int streams_get_mixbuffers (void *** bufferlist, struct roar_audio_info * info, unsigned int pos) {
1955 static void * bufs[ROAR_STREAMS_MAX+1];
1956 int i;
1957 int have = 0;
1958 int dir;
1959
1960 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
1961  if ( g_streams[i] != NULL ) {
1962   dir = streams_get_dir(i);
1963
1964   switch (dir) {
1965    case ROAR_DIR_PLAY:
1966    case ROAR_DIR_BIDIR:
1967    case ROAR_DIR_RECPLAY:
1968     break;
1969    case ROAR_DIR_BRIDGE:
1970      if ( g_streams[i]->buffer == NULL )
1971       continue;
1972     break;
1973    default:
1974      continue;
1975   }
1976
1977   if ( streams_get_flag(i, ROAR_FLAG_PAUSE) )
1978    continue;
1979
1980   if ( streams_get_outputbuffer(i, &bufs[have], ROAR_OUTPUT_CALC_OUTBUFSIZE(info)) == -1 ) {
1981    ROAR_ERR("streams_get_mixbuffer(*): Can not alloc output buffer for stream %i, BAD!", i);
1982    ROAR_ERR("streams_get_mixbuffer(*): Ignoring stream for this round.");
1983    continue;
1984   }
1985   if ( streams_fill_mixbuffer2(i, info) == -1 ) {
1986    ROAR_ERR("streams_get_mixbuffer(*): Can not fill output buffer for stream %i, this should not happen", i);
1987    continue;
1988   }
1989
1990//   printf("D: bufs[have=%i] = %p\n", have, bufs[have]);
1991
1992   ROAR_DBG("streams_get_mixbuffers(*):  bufs[have] = %p", bufs[have]);
1993   ROAR_DBG("streams_get_mixbuffers(*): *bufs[have] = 0x%08x...", *(uint32_t*)bufs[have]);
1994
1995   if ( !streams_get_flag(i, ROAR_FLAG_MUTE) )
1996    have++; // we have a new stream!
1997  }
1998 }
1999
2000 bufs[have] = NULL;
2001 //printf("D: bufs[have=%i] = %p\n", have, bufs[have]);
2002
2003 ROAR_DBG("streams_get_mixbuffers(*): have = %i", have);
2004
2005 *bufferlist = bufs;
2006 return have;
2007}
2008
2009
2010int stream_add_buffer  (int id, struct roar_buffer ** buf) {
2011 ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = ?", id, buf);
2012
2013 _CHECK_SID(id);
2014
2015 if ( g_streams[id]->buffer == NULL ) {
2016  g_streams[id]->buffer = *buf;
2017  *buf = NULL;
2018  ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = 0", id, buf);
2019  return 0;
2020 }
2021
2022 ROAR_DBG("stream_add_buffer(id=%i, buf=%p) = ?", id, buf);
2023 return roar_buffer_moveinto(g_streams[id]->buffer, buf);
2024}
2025
2026int stream_shift_out_buffer   (int id, void * data, size_t * len) {
2027 _CHECK_SID(id);
2028
2029 if ( g_streams[id]->buffer == NULL )
2030  return -1;
2031
2032 return roar_buffer_shift_out(&(g_streams[id]->buffer), data, len);
2033}
2034
2035int stream_outputbuffer_request(int id, struct roar_buffer ** buf, size_t len) {
2036 register struct roar_stream_server *  ss;
2037 size_t buflen;
2038 void * bufdata;
2039 int ret;
2040
2041 _CHECK_SID(id);
2042
2043 if ( (ss = g_streams[id]) == NULL )
2044  return -1;
2045
2046 if ( buf != NULL ) /* just be be sure */
2047  *buf = NULL;
2048
2049 if ( ss->outputbuffer != NULL ) {
2050  if ( roar_buffer_get_len(ss->outputbuffer, &buflen) == 0 ) {
2051   if ( buflen == len ) {
2052    if ( buf != NULL )
2053     *buf = ss->outputbuffer;
2054    return 0;
2055   } else if ( buflen > len ) {
2056    if ( roar_buffer_set_len(ss->outputbuffer, len) == 0 ) {
2057     if ( buf != NULL )
2058      *buf = ss->outputbuffer;
2059     return 0;
2060    }
2061   }
2062  }
2063
2064  // if the buffer is not suitable:
2065
2066  ret = roar_buffer_free(ss->outputbuffer);
2067  ss->outputbuffer = NULL;
2068  if ( ret == -1 )
2069   return ret;
2070 }
2071
2072 if ( roar_buffer_new(&(ss->outputbuffer), len) == -1 )
2073  return -1;
2074
2075 if ( roar_buffer_get_data(ss->outputbuffer, &bufdata) == -1 ) {
2076  roar_buffer_free(ss->outputbuffer);
2077  ss->outputbuffer = NULL;
2078  return -1;
2079 }
2080
2081 memset(bufdata, 0, len);
2082
2083 if ( buf != NULL )
2084  *buf = ss->outputbuffer;
2085
2086 return 0;
2087}
2088
2089int stream_outputbuffer_destroy(int id) {
2090 int ret;
2091 register struct roar_stream_server *  ss;
2092
2093 _CHECK_SID(id);
2094
2095 if ( (ss = g_streams[id]) == NULL )
2096  return -1;
2097
2098 if ( ss->outputbuffer != NULL ) {
2099  ret = roar_buffer_free(ss->outputbuffer);
2100  ss->outputbuffer = NULL;
2101  return ret;
2102 }
2103
2104 return 0;
2105}
2106
2107int stream_prethru_add(int id, struct roar_buffer ** buf) {
2108 register struct roar_stream_server *  ss;
2109
2110 _CHECK_SID(id);
2111
2112 if ( (ss = g_streams[id]) == NULL )
2113  return -1;
2114
2115 if ( ss->prethru == NULL ) {
2116  ss->prethru = *buf;
2117  *buf = NULL;
2118  return 0;
2119 }
2120
2121 if ( roar_buffer_moveinto(ss->prethru, buf) == -1 ) {
2122  return -1;
2123 }
2124
2125 return 0;
2126}
2127
2128int stream_prethru_add_data(int id, void ** buf, size_t len) {
2129 struct roar_buffer * buffer;
2130
2131 _CHECK_SID(id);
2132
2133 if ( roar_buffer_new_data(&buffer, len, buf) == -1 )
2134  return -1;
2135
2136 if ( stream_prethru_add(id, &buffer) == -1 ) {
2137  roar_buffer_free(buffer);
2138  return -1;
2139 }
2140
2141 return 0;
2142}
2143
2144int stream_prethru_destroy(int id) {
2145 int ret;
2146 register struct roar_stream_server *  ss;
2147
2148 _CHECK_SID(id);
2149
2150 if ( (ss = g_streams[id]) == NULL )
2151  return -1;
2152
2153 if ( ss->prethru != NULL ) {
2154  ret = roar_buffer_free(ss->prethru);
2155  ss->prethru = NULL;
2156  return ret;
2157 }
2158
2159 return 0;
2160}
2161
2162int stream_prethru_send(int dst, int src) {
2163 struct roar_stream_server *  dst_ss, * src_ss;
2164 struct roar_buffer * bufbuf;
2165 void * bufdata;
2166 size_t buflen;
2167
2168 ROAR_DBG("stream_prethru_send(dst=%i, src=%i) = ?", dst, src);
2169
2170 _CHECK_SID(dst);
2171 _CHECK_SID(src);
2172
2173 if ( (dst_ss = g_streams[dst]) == NULL )
2174  return -1;
2175
2176 if ( (src_ss = g_streams[src]) == NULL )
2177  return -1;
2178
2179 bufbuf = src_ss->prethru;
2180
2181 ROAR_DBG("stream_prethru_send(dst=%i, src=%i): prethru buffer at %p", dst, src, bufbuf);
2182
2183 roar_buffer_foreach(bufbuf) {
2184  ROAR_DBG("stream_prethru_send(dst=%i, src=%i): looping with buffer at %p", dst, src, bufbuf);
2185
2186  if ( roar_buffer_get_data(bufbuf, &bufdata) == -1 )
2187   return -1;
2188
2189  if ( roar_buffer_get_len(bufbuf, &buflen) == -1 )
2190   return -1;
2191
2192  if ( stream_vio_s_write(dst_ss, bufdata, buflen) != buflen )
2193   return -1;
2194 }
2195
2196 ROAR_DBG("stream_prethru_send(dst=%i, src=%i) = 0", dst, src);
2197 return 0;
2198}
2199
2200int streams_check  (int id) {
2201 int fh;
2202 ssize_t req, realreq, done;
2203 struct roar_stream        *   s;
2204 struct roar_stream_server *  ss;
2205 struct roar_buffer        *   b;
2206 void                      * buf;
2207// char                        tmp;
2208
2209 _CHECK_SID(id);
2210
2211 ROAR_DBG("streams_check(id=%i) = ?", id);
2212
2213 s = ROAR_STREAM(ss = g_streams[id]);
2214
2215 if ( (fh = s->fh) == -1 )
2216  return 0;
2217
2218 if ( streams_get_flag(id, ROAR_FLAG_PAUSE) )
2219  return 0;
2220
2221 switch (s->dir) {
2222  case ROAR_DIR_LIGHT_IN:
2223#ifndef ROAR_WITHOUT_DCOMP_LIGHT
2224    return light_check_stream(id);
2225#else
2226    streams_delete(id);
2227    return -1;
2228#endif
2229   break;
2230  case ROAR_DIR_MIDI_IN:
2231#ifndef ROAR_WITHOUT_DCOMP_MIDI
2232    return midi_check_stream(id);
2233#else
2234    streams_delete(id);
2235    return -1;
2236#endif
2237   break;
2238  case ROAR_DIR_RAW_IN:
2239#ifndef ROAR_WITHOUT_DCOMP_RAW
2240    return raw_check_stream(id);
2241#else
2242    streams_delete(id);
2243    return -1;
2244#endif
2245   break;
2246  case ROAR_DIR_RDTCS_IN:
2247#ifndef ROAR_WITHOUT_DCOMP_RDTCS
2248    return rdtcs_check_stream(id);
2249#else
2250    streams_delete(id);
2251    return -1;
2252#endif
2253   break;
2254  case ROAR_DIR_PLAY:
2255  case ROAR_DIR_BIDIR:
2256  case ROAR_DIR_RECPLAY:
2257   break;
2258  case ROAR_DIR_OUTPUT:
2259    if ( !streams_get_flag(id, ROAR_FLAG_RECSOURCE) )
2260     return 0;
2261   break;
2262  default:
2263/*
2264    ROAR_WARN("streams_check(id=%i): Read event on non input stream of type/dir %s", id, roar_dir2str(s->dir));
2265    errno = 0;
2266    req = stream_vio_s_read(ss, &tmp, 1);
2267    ROAR_DBG("streams_check(id=%i): stream_vio_s_read(ss, &tmp, 1) = %li // errno=%s(%i)", id, req, strerror(errno), errno);
2268    if ( req == 1 ) {
2269     ROAR_ERR("streams_check(id=%i): Client violates protocol, got one byte of data on output stream, kicking stream");
2270     streams_delete(id);
2271     return -1;
2272    }
2273*/
2274    return 0;
2275   break;
2276 }
2277
2278 ROAR_DBG("streams_check(id=%i): fh = %i", id, fh);
2279
2280/*
2281 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);
2282*/
2283
2284 req  = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info)); // optimal size
2285// req  = ROAR_OUTPUT_BUFFER_SAMPLES * s->info.channels * (s->info.bits / 8) * ((float)s->info.rate/g_sa->rate);
2286 req += ss->need_extra; // bytes left we sould get....
2287
2288 ROAR_DBG("streams_check(id=%i): asking for %i bytes", id, req);
2289
2290 if ( roar_buffer_new_data(&b, req, &buf) == -1 ) {
2291  ROAR_ERR("streams_check(*): Can not alloc buffer space!");
2292  ROAR_DBG("streams_check(*) = -1");
2293  return -1;
2294 }
2295
2296 ROAR_DBG("streams_check(id=%i): buffer is up and ready ;)", id);
2297 ROAR_DBG("streams_check(id=%i): asking for %i bytes", id, req);
2298
2299 if ( ss->codecfilter == -1 ) {
2300  realreq = req;
2301/*
2302  req = read(fh, buf, req);
2303  if ( req < realreq ) { // we can do this as the stream is in nonblocking mode!
2304   if ( (realreq = read(fh, buf+req, realreq-req)) > 0 )
2305    req += realreq;
2306  }
2307*/
2308  done = 0;
2309  while (req > 0 && done != realreq) {
2310   if ( (req = stream_vio_s_read(ss, buf+done, realreq-done)) > 0 )
2311    done += req;
2312  }
2313  req = done;
2314
2315 } else {
2316  req = codecfilter_read(ss->codecfilter_inst, ss->codecfilter, buf, req);
2317 }
2318
2319 if ( req > 0 ) {
2320  ROAR_DBG("streams_check(id=%i): got %i bytes", id, req);
2321
2322  if ( roar_buffer_set_len(b, req) != -1 ) {
2323   if ( stream_add_buffer(id, &b) != -1 )
2324    return 0;
2325
2326   ROAR_ERR("streams_check(id=%i): something is wrong, could not add buffer to stream!", id);
2327  } else {
2328   ROAR_ERR("streams_check(id=%i): something is wrong, could not set size of buffer!", id);
2329  }
2330
2331  roar_buffer_free(b);
2332 } else {
2333  ROAR_DBG("streams_check(id=%i): read() = %i // errno: %s", id, req, strerror(errno));
2334#ifdef ROAR_HAVE_LIBVORBISFILE
2335  if ( errno != EAGAIN && errno != ESPIPE ) { // libvorbis file trys to seek a bit ofen :)
2336#else
2337  if ( errno != EAGAIN ) {
2338#endif
2339   ROAR_DBG("streams_check(id=%i): EOF!", id);
2340   streams_delete(id);
2341   ROAR_DBG("streams_check(id=%i) = 0", id);
2342  }
2343  roar_buffer_free(b);
2344  return 0;
2345 }
2346
2347
2348 ROAR_DBG("streams_check(id=%i) = -1", id);
2349 return -1;
2350}
2351
2352
2353#define _return(x) return (x)
2354int streams_send_mon   (int id) {
2355// int fh;
2356 struct roar_stream        *   s;
2357 struct roar_stream_server *  ss;
2358 struct roar_buffer        *  bufbuf = NULL;
2359 struct roar_remove_state     removalstate;
2360 void  * ip              = g_output_buffer;
2361 void  * obuf;
2362 int     olen;
2363 int     is_the_same     = 1;
2364 int     is_vol_eq       = 1;
2365 int     is_muted;
2366 int     antiecho        = 0;
2367 ssize_t ret;
2368
2369 _CHECK_SID(id);
2370
2371 ROAR_DBG("streams_send_mon(id=%i) = ?", id);
2372
2373 s = ROAR_STREAM((ss = g_streams[id]));
2374
2375/*
2376 if ( (fh = s->fh) == -1 )
2377  return 0;
2378*/
2379
2380 if ( !ss->ready )
2381  return 0;
2382
2383 if ( g_config->jumbo_mtu )
2384  roar_vio_sync(ss->viop);
2385
2386 if ( streams_get_flag(id, ROAR_FLAG_PAUSE) )
2387  return 0;
2388
2389 switch (s->dir) {
2390  case ROAR_DIR_LIGHT_OUT:
2391#ifndef ROAR_WITHOUT_DCOMP_LIGHT
2392    return light_send_stream(id);
2393#else
2394    streams_delete(id);
2395    return -1;
2396#endif
2397   break;
2398  case ROAR_DIR_MIDI_OUT:
2399#ifndef ROAR_WITHOUT_DCOMP_MIDI
2400    return midi_send_stream(id);
2401#else
2402    streams_delete(id);
2403    return -1;
2404#endif
2405   break;
2406  case ROAR_DIR_RDTCS_OUT:
2407#ifndef ROAR_WITHOUT_DCOMP_RDTCS
2408    return rdtcs_send_stream(id);
2409#else
2410    streams_delete(id);
2411    return -1;
2412#endif
2413   break;
2414
2415  case ROAR_DIR_COMPLEX_OUT:
2416    // send a tick:
2417    if ( ss->codecfilter != -1 ) {
2418     if ( codecfilter_write(ss->codecfilter_inst, ss->codecfilter, NULL, 0) == 0 )
2419      if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2420       //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2421       _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2422      }
2423    }
2424    return 0;
2425   break;
2426
2427  case ROAR_DIR_OUTPUT:
2428    if ( g_standby )
2429     return 0;
2430  case ROAR_DIR_MONITOR:
2431  case ROAR_DIR_BIDIR:
2432   break;
2433
2434  case ROAR_DIR_RECORD:
2435  case ROAR_DIR_RECPLAY:
2436    ip = g_input_buffer;
2437   break;
2438  default:
2439    return 0;
2440   break;
2441 }
2442
2443
2444 ROAR_DBG("streams_send_mon(id=%i): fh = %i", id, s->fh);
2445
2446 if ( s->info.channels != g_sa->channels || s->info.bits  != g_sa->bits ||
2447      s->info.rate     != g_sa->rate     || s->info.codec != g_sa->codec  )
2448  is_the_same = 0;
2449
2450 is_muted = streams_get_flag(id, ROAR_FLAG_MUTE);
2451
2452 if ( !is_muted && !streams_get_flag(id, ROAR_FLAG_HWMIXER) ) {
2453  is_vol_eq = need_vol_change(g_sa->channels, &(ss->mixer)) ? 0 : 1;
2454 }
2455
2456 if ( streams_get_flag(id, ROAR_FLAG_ANTIECHO) )
2457  antiecho = 1;
2458
2459 if ( !is_the_same || !is_vol_eq || antiecho || is_muted ) {
2460  olen = ROAR_OUTPUT_CALC_OUTBUFSIZE(&(s->info)); // we hope g_output_buffer_len
2461                                                  // is ROAR_OUTPUT_CALC_OUTBUFSIZE(g_sa) here
2462  if ( stream_outputbuffer_request(id, &bufbuf, ROAR_OUTPUT_CALC_OUTBUFSIZE_MAX(&(s->info), g_sa)) == -1 )
2463   return -1;
2464
2465  if ( roar_buffer_get_data(bufbuf, &obuf) == -1 ) {
2466   _return(-1);
2467  }
2468
2469  ROAR_DBG("streams_send_mon(id=%i): obuf=%p, olen=%i", id, obuf, olen);
2470 } else {
2471  obuf = ip;
2472  olen = g_output_buffer_len;
2473 }
2474
2475 if ( antiecho ) {
2476  ROAR_DBG("streams_send_mon(id=%i): antiecho=%i", id, antiecho);
2477  if ( roar_remove_init(&removalstate) == -1 ) {
2478   _return(-1);
2479  }
2480
2481  ROAR_DBG("streams_send_mon(id=%i): antiecho=%i", id, antiecho);
2482  if ( roar_remove_so(obuf, ip, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa->bits, &removalstate) == -1 ) {
2483   ROAR_DBG("streams_send_mon(id=%i): anti echo failed", id);
2484   _return(-1);
2485  }
2486  ROAR_DBG("streams_send_mon(id=%i): antiecho=%i", id, antiecho);
2487 }
2488
2489 if ( !is_vol_eq ) {
2490  if ( roar_amp_pcm(obuf, g_sa->bits, ip, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa->channels, &(ss->mixer)) == -1 ) {
2491   _return(-1);
2492  }
2493
2494  ip = obuf;
2495 }
2496
2497 if ( is_muted ) {
2498  memset(obuf, 0, (g_sa->bits*ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels)/8);
2499  ip = obuf;
2500 }
2501
2502 streams_ltm_calc(id, &(s->info), ip, (ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels*g_sa->bits)/8);
2503
2504 if ( !is_the_same ) {
2505  if ( roar_conv(obuf, ip, ROAR_OUTPUT_BUFFER_SAMPLES*g_sa->channels, g_sa, &(s->info)) == -1 ) {
2506   _return(-1);
2507  }
2508 }
2509
2510 roar_err_clear_errno();
2511
2512 if ( ss->codecfilter == -1 ) {
2513  ROAR_DBG("streams_send_mon(id=%i): not a CF stream", id);
2514  if ( s->fh == -1 && ss->vio.inst == NULL ) {
2515   ROAR_DBG("streams_send_mon(id=%i) = 0", id);
2516   _return(0);
2517  }
2518
2519  ROAR_DBG("streams_send_mon(id=%i) = ?", id);
2520
2521  if ( (ret = stream_vio_s_write(ss, obuf, olen)) == olen ) {
2522   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
2523   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2524    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2525    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2526   }
2527   ROAR_DBG("streams_send_mon(id=%i) = 0", id);
2528   _return(0);
2529  }
2530
2531  ROAR_DBG("streams_send_mon(id=%i) = ?", id);
2532
2533  if ( ret > 0 && roar_err_is_errno_clear() ) {
2534   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);
2535   roar_notify_core_emit_simple(ROAR_OE_STREAM_XRUN, -1, id, ROAR_OT_STREAM, ROAR_XRUN_OVER_POST, -1, NULL, 0);
2536   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), ret)*s->info.channels);
2537   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2538    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2539    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2540   }
2541   _return(0);
2542  }
2543 } else {
2544  if ( codecfilter_write(ss->codecfilter_inst, ss->codecfilter, obuf, olen)
2545            == olen ) {
2546   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
2547   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2548    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2549    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2550   }
2551   _return(0);
2552  } else { // we cann't retry on codec filetered streams
2553   if ( errno != EAGAIN ) {
2554    streams_delete(id);
2555    _return(-1);
2556   }
2557  }
2558 }
2559
2560 if ( errno == EAGAIN ) {
2561  // ok, the client blocks for a moment, we try to sleep a bit an retry in the hope not to
2562  // make any gapes in any output because of this
2563
2564#ifdef ROAR_HAVE_USLEEP
2565  roar_usleep(100); // 0.1ms
2566#endif
2567
2568  if ( stream_vio_s_write(ss, obuf, olen) == olen ) {
2569   s->pos = ROAR_MATH_OVERFLOW_ADD(s->pos, ROAR_OUTPUT_CALC_OUTBUFSAMP(&(s->info), olen)*s->info.channels);
2570   if ( ss->state != ROAR_STREAMSTATE_OLD ) {
2571    //ROAR_INFO("streams_send_mon(id=%i): stream state: %s->old", ROAR_DBG_INFO_VERBOSE, id, roar_streamstate2str(ss->state));
2572    _streams_change_state(ss, ROAR_STREAMSTATE_OLD, "streams_send_mon");
2573   }
2574   _return(0);
2575  } else if ( errno == EAGAIN ) {
2576   ROAR_WARN("streams_send_mon(id=%i): Can not send data to client: %s", id, strerror(errno));
2577   _return(0);
2578  }
2579 }
2580
2581 // ug... error... delete stream!
2582
2583 streams_delete(id);
2584
2585 _return(-1);
2586}
2587#undef _return
2588
2589int streams_send_filter_all(void) {
2590 struct roar_stream_server *  ss;
2591 int i;
2592
2593 for (i = 0; i < ROAR_STREAMS_MAX; i++) {
2594  if ( (ss = g_streams[i]) == NULL )
2595   continue;
2596
2597  if ( ROAR_STREAM(ss)->dir != ROAR_DIR_FILTER )
2598   continue;
2599
2600  if ( !ss->ready )
2601   continue;
2602
2603  if ( ss->state == ROAR_STREAMSTATE_CLOSING )
2604   continue;
2605
2606  streams_send_filter(i);
2607 }
2608
2609 return 0;
2610}
2611
2612int streams_send_filter(int id) {
2613 int fh;
2614 int have = 0;
2615 int len;
2616 struct roar_stream        *   s;
2617 struct roar_stream_server *  ss;
2618
2619 _CHECK_SID(id);
2620
2621 ROAR_DBG("streams_send_filter(id=%i) = ?", id);
2622
2623 s = ROAR_STREAM(ss = g_streams[id]);
2624
2625 if ( (fh = s->fh) == -1 )
2626  return 0;
2627
2628 if ( s->dir != ROAR_DIR_FILTER )
2629  return 0;
2630
2631 if ( streams_get_flag(id, ROAR_FLAG_PAUSE) )
2632  return 0;
2633
2634
2635 ROAR_DBG("streams_send_filter(id=%i): fh = %i", id, fh);
2636
2637 if ( stream_vio_s_write(ss, g_output_buffer, g_output_buffer_len) == g_output_buffer_len ) {
2638  while ( have < g_output_buffer_len ) {
2639   if ( (len = stream_vio_s_read(ss, g_output_buffer+have, g_output_buffer_len-have)) < 1 ) {
2640    streams_delete(id);
2641    return -1;
2642   }
2643   have += len;
2644  }
2645  return 0;
2646 }
2647
2648 // ug... error... delete stream!
2649
2650 streams_delete(id);
2651
2652 return -1;
2653}
2654
2655
2656// VIO:
2657
2658ssize_t stream_vio_read (int stream, void *buf, size_t count) {
2659 _CHECK_SID(stream);
2660
2661 return stream_vio_s_read(g_streams[stream], buf, count);
2662}
2663
2664ssize_t stream_vio_write(int stream, void *buf, size_t count) {
2665 _CHECK_SID(stream);
2666
2667 return stream_vio_s_write(g_streams[stream], buf, count);
2668}
2669
2670int     stream_vio_ctl  (int stream, roar_vio_ctl_t cmd,   void * data) {
2671 _CHECK_SID(stream);
2672
2673 return stream_vio_s_ctl(g_streams[stream], cmd, data);
2674}
2675
2676ssize_t stream_vio_s_read (struct roar_stream_server * stream, void *buf, size_t count) {
2677 void    * orig_buf = buf;
2678  size_t   len      =  0;
2679 ssize_t   r        = -1;
2680 int       i;
2681
2682 errno = 0;
2683
2684 if ( stream == NULL ) {
2685  roar_err_set(ROAR_ERROR_FAULT);
2686  return -1;
2687 }
2688
2689 if ( stream->vio.read == NULL ) {
2690  roar_err_set(ROAR_ERROR_NOTSUP);
2691  return -1;
2692 }
2693
2694 while ( (r = roar_vio_read(&(stream->vio), buf, count)) > 0 ) {
2695  len   += r;
2696  buf   += r;
2697  count -= r;
2698  if ( count == 0 )
2699   break;
2700 }
2701
2702 if ( len == 0 && r == -1 )
2703  return -1;
2704
2705 if ( streams_thru_num ) {
2706  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
2707   if ( g_streams[i] != NULL && ROAR_STREAM(g_streams[i])->pos_rel_id == ROAR_STREAM(stream)->id ) {
2708    if ( ROAR_STREAM(g_streams[i])->dir == ROAR_DIR_THRU ) {
2709     if ( g_streams[i]->ready ) {
2710      if ( stream_vio_write(i, orig_buf, len) != len )
2711       streams_delete(i);
2712
2713      if ( g_streams[i] != NULL ) {
2714       if ( g_streams[i]->state != ROAR_STREAMSTATE_OLD ) {
2715        //ROAR_INFO("stream_vio_s_read(*): (stream: %i) stream state: %s->old", ROAR_DBG_INFO_VERBOSE, i, roar_streamstate2str(g_streams[i]->state));
2716        _streams_change_state(g_streams[i], ROAR_STREAMSTATE_OLD, "stream_vio_s_read");
2717       }
2718      }
2719     }
2720    }
2721   }
2722  }
2723 }
2724
2725 return len;
2726}
2727
2728ssize_t stream_vio_s_write(struct roar_stream_server * stream, void *buf, size_t count) {
2729 int i;
2730
2731 errno = 0;
2732
2733 if ( stream == NULL ) {
2734  roar_err_set(ROAR_ERROR_FAULT);
2735  return -1;
2736 }
2737
2738// ROAR_WARN("stream_vio_s_write(*): writing...");
2739
2740 if ( streams_thru_num ) {
2741  for (i = 0; i < ROAR_STREAMS_MAX; i++) {
2742   if ( g_streams[i] != NULL && ROAR_STREAM(g_streams[i])->pos_rel_id == ROAR_STREAM(stream)->id ) {
2743    if ( ROAR_STREAM(g_streams[i])->dir == ROAR_DIR_THRU ) {
2744     if ( g_streams[i]->ready ) {
2745      if ( g_streams[i]->state == ROAR_STREAMSTATE_NEW ) {
2746       if ( streams_get_flag(i, ROAR_FLAG_PRETHRU) == 1 ) {
2747        if ( stream_prethru_send(i, ROAR_STREAM(stream)->id) == -1 ) {
2748         streams_delete(i);
2749        }
2750       }
2751      }
2752
2753      if ( stream_vio_write(i, buf, count) != count ) {
2754       streams_delete(i);
2755      }
2756
2757      if ( g_streams[i] != NULL ) {
2758       if ( g_streams[i]->state != ROAR_STREAMSTATE_OLD ) {
2759        //ROAR_INFO("stream_vio_s_write(*): (stream: %i) stream state: %s->old", ROAR_DBG_INFO_VERBOSE, i, roar_streamstate2str(g_streams[i]->state));
2760        _streams_change_state(g_streams[i], ROAR_STREAMSTATE_OLD, "stream_vio_s_write");
2761       }
2762      }
2763     }
2764    }
2765   }
2766  }
2767 }
2768
2769 if ( g_config->jumbo_mtu ) {
2770  if ( stream->viop != &(stream->jumbo) ) {
2771   if ( roar_vio_open_jumbo(&(stream->jumbo), &(stream->vio), g_config->jumbo_mtu) != -1 ) {
2772    // if that works we continue using the jumbo vio,
2773    // in case it didn't we dont, just use normal VIO.
2774    stream->viop = &(stream->jumbo);
2775   }
2776  }
2777 }
2778
2779 return roar_vio_write(stream->viop, buf, count);
2780}
2781
2782int     stream_vio_s_ctl  (struct roar_stream_server * stream, roar_vio_ctl_t cmd,   void * data) {
2783 if ( stream == NULL ) {
2784  roar_err_set(ROAR_ERROR_FAULT);
2785  return -1;
2786 }
2787
2788 return roar_vio_ctl(stream->viop, cmd, data);
2789}
2790
2791//ll
Note: See TracBrowser for help on using the repository browser.