source: roaraudio/roard/streams.c @ 4552:47a0412f706d

Last change on this file since 4552:47a0412f706d was 4552:47a0412f706d, checked in by phi, 14 years ago

implemented flag toggling and flag protection

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