source: roaraudio/roard/streams.c @ 4847:8af3ac8d139a

Last change on this file since 4847:8af3ac8d139a was 4847:8af3ac8d139a, checked in by phi, 13 years ago

correctly reset RECSOURCE flag in case of stream delete

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