source: roaraudio/roard/streams.c @ 4543:14019152e072

Last change on this file since 4543:14019152e072 was 4543:14019152e072, checked in by phi, 14 years ago

implemented some very basic single sink mode, corrected streams_get_mixer_stream()

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