source: roaraudio/roard/streams.c @ 4847:8af3ac8d139a

Last change on this file since 4847:8af3ac8d139a was 4847:8af3ac8d139a, checked in by phi, 13 years ago

correctly reset RECSOURCE flag in case of stream delete

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