source: roaraudio/roard/streams.c @ 6056:8d4468a24909

Last change on this file since 6056:8d4468a24909 was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

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