source: roaraudio/roard/streams.c @ 5889:d866fb1213d6

Last change on this file since 5889:d866fb1213d6 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

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