source: roaraudio/roard/streams.c @ 4815:df2ef6edb97f

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

added support to roard for record streams.

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