source: roaraudio/roard/streams.c @ 4819:bfe88a001985

Last change on this file since 4819:bfe88a001985 was 4819:bfe88a001985, checked in by phi, 13 years ago

avoid warning when record stream is not yet fully up

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