source: roaraudio/roard/streams.c @ 5889:d866fb1213d6

Last change on this file since 5889:d866fb1213d6 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

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