source: roaraudio/roard/streams.c @ 5192:4237437ca526

Last change on this file since 5192:4237437ca526 was 5192:4237437ca526, checked in by phi, 12 years ago

declare some stuff 'extern', this saves like 5.3KB of diskspace in plugin files and make them more resistant against changes in roard

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