source: roaraudio/roard/streams.c @ 4753:fae4e9e389bc

Last change on this file since 4753:fae4e9e389bc was 4753:fae4e9e389bc, checked in by phi, 13 years ago

fixed depends

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