source: roaraudio/roard/streams.c @ 4753:fae4e9e389bc

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

fixed depends

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