source: roaraudio/roard/streams.c @ 5961:06e7fd9e4c25

Last change on this file since 5961:06e7fd9e4c25 was 5961:06e7fd9e4c25, checked in by phi, 10 years ago

Updates of copyright and license headers

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