source: roaraudio/roard/streams.c @ 5381:430b1d26e12d

Last change on this file since 5381:430b1d26e12d was 5381:430b1d26e12d, checked in by phi, 12 years ago

updated copyright years

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