source: roaraudio/roard/streams.c @ 4099:6425c5901202

Last change on this file since 4099:6425c5901202 was 4099:6425c5901202, checked in by phi, 14 years ago

added still useless parent_stream struct member

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