source: roaraudio/roard/streams.c @ 4546:653a785ffc38

Last change on this file since 4546:653a785ffc38 was 4546:653a785ffc38, checked in by phi, 13 years ago

avoid wrong counter on flag multiple times set

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