source: roaraudio/roard/streams.c @ 5242:97239101cee9

Last change on this file since 5242:97239101cee9 was 5242:97239101cee9, checked in by phi, 12 years ago

some roard compiler warnings cleanup

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