source: roaraudio/roard/streams.c @ 5374:5810df1d6fb9

Last change on this file since 5374:5810df1d6fb9 was 5374:5810df1d6fb9, checked in by phi, 12 years ago

cleanup

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