source: roaraudio/roard/streams.c @ 4229:7e755981f03f

Last change on this file since 4229:7e755981f03f was 4229:7e755981f03f, checked in by phi, 14 years ago

only take PASSFH if stream is not yet connected

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