source: roaraudio/roard/streams.c @ 4236:1d583a76aa06

Last change on this file since 4236:1d583a76aa06 was 4229:7e755981f03f, checked in by phi, 14 years ago

only take PASSFH if stream is not yet connected

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