source: roaraudio/libroar/vs.c @ 4579:d6f55bf4b6d4

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

added support for ROAR_VS_WAIT (Closes: #54)

File size: 16.3 KB
RevLine 
[4173]1//vs.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar 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 *  libroar 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
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
[4174]38#define FLAG_NONE     0x0000
39#define FLAG_STREAM   0x0001
[4175]40#define FLAG_NONBLOCK 0x0002
[4206]41#define FLAG_BUFFERED 0x0004
[4174]42
[4186]43#define _initerr()  do { errno = 0; roar_err_clear(); } while(0)
44#define _seterr(x)  do { if ( error != NULL ) *error = (x); } while(0)
45#define _seterrre() do { _seterr(roar_errno); } while(0)
46#define _seterrse() do { roar_err_from_errno(); _seterr(roar_errno); } while(0)
[4260]47#define _ckvss(ret) do { if ( vss == NULL ) { _seterr(ROAR_ERROR_INVAL); return (ret); } } while(0)
[4174]48
49struct roar_vs {
50 int flags;
51 struct roar_connection con_store;
52 struct roar_connection * con;
53 struct roar_stream       stream;
54 struct roar_vio_calls    vio;
[4206]55 struct roar_audio_info   info;
56 size_t                   readc, writec;
57 int                      mixerid;
58 int                      first_primid;
[4174]59};
60
[4206]61static int _roar_vs_find_first_prim(roar_vs_t * vss);
62
[4174]63const char * roar_vs_strerr(int error) {
64 const struct {
65  int err;
66  const char * msg;
67 } msgs[] = {
[4181]68  {ROAR_ERROR_NONE,        "No error"},
69  {ROAR_ERROR_PERM,        "Operation not permitted"},
70  {ROAR_ERROR_NOENT,       "No such object, file or directory"},
71  {ROAR_ERROR_BADMSG,      "Bad message"},
72  {ROAR_ERROR_BUSY,        "Device or resource busy"},
73  {ROAR_ERROR_CONNREFUSED, "Connection refused"},
74  {ROAR_ERROR_NOSYS,       "Function not implemented"},
75  {ROAR_ERROR_NOTSUP,      "Operation not supported"},
76  {ROAR_ERROR_PIPE,        "Broken pipe"},
77  {ROAR_ERROR_PROTO,       "Protocol error"},
78  {ROAR_ERROR_RANGE,       "Result too large or parameter out of range"},
79  {ROAR_ERROR_MSGSIZE,     "Message too long"},
80  {ROAR_ERROR_NOMEM,       "Not enough space"},
81  {ROAR_ERROR_INVAL,       "Invalid argument"},
[4174]82  {-1, NULL}
83 };
84 int i;
85
86 for (i = 0; msgs[i].msg != NULL; i++)
87  if ( msgs[i].err == error )
88   return msgs[i].msg;
89
90 return "(unknown)";
91}
92
93static roar_vs_t * roar_vs_init(int * error) {
94 roar_vs_t * vss = roar_mm_malloc(sizeof(roar_vs_t));
95
96 if ( vss == NULL ) {
[4186]97  _seterrse();
[4174]98  return NULL;
99 }
100
101 memset(vss, 0, sizeof(roar_vs_t));
102
[4206]103 vss->mixerid      = -1;
104 vss->first_primid = -1;
105
[4174]106 return vss;
107}
108
109roar_vs_t * roar_vs_new_from_con(struct roar_connection * con, int * error) {
110 roar_vs_t * vss = roar_vs_init(error);
111
112 if ( vss == NULL )
113  return NULL;
114
115 vss->con = con;
116
117 return vss;
118}
119
120roar_vs_t * roar_vs_new(const char * server, const char * name, int * error) {
121 roar_vs_t * vss = roar_vs_init(error);
122 int ret;
123
124 if ( vss == NULL )
125  return NULL;
126
127 vss->con = &(vss->con_store);
128
[4186]129 _initerr();
130
[4174]131 ret = roar_simple_connect(vss->con, (char*)server, (char*)name);
132
133 if ( ret == -1 ) {
134  roar_vs_close(vss, ROAR_VS_TRUE, NULL);
[4186]135  _seterrre();
[4174]136  return NULL;
137 }
138
139 return vss;
140}
141
142int roar_vs_stream(roar_vs_t * vss, const struct roar_audio_info * info, int dir, int * error) {
[4206]143 struct roar_stream_info sinfo;
[4174]144 int ret;
145
[4260]146 _ckvss(-1);
147
[4174]148 if ( vss->flags & FLAG_STREAM ) {
149  _seterr(ROAR_ERROR_INVAL);
150  return -1;
151 }
152
[4186]153 _initerr();
154
[4206]155 if ( info != &(vss->info) )
156  memcpy(&(vss->info), info, sizeof(struct roar_audio_info));
157
[4174]158 ret = roar_vio_simple_new_stream_obj(&(vss->vio), vss->con, &(vss->stream),
159                                      info->rate, info->channels, info->bits, info->codec,
160                                      dir
161                                     );
162
163 if ( ret == -1 ) {
[4186]164  _seterrre();
[4174]165  return -1;
166 }
167
[4206]168 if ( roar_stream_get_info(vss->con, &(vss->stream), &sinfo) != -1 ) {
169  vss->mixerid = sinfo.mixer;
170  _roar_vs_find_first_prim(vss);
171 }
172
[4174]173 vss->flags |= FLAG_STREAM;
174
175 return 0;
176}
177
178roar_vs_t * roar_vs_new_simple(const char * server, const char * name, int rate, int channels, int codec, int bits, int dir, int * error) {
179 roar_vs_t * vss = roar_vs_new(server, name, error);
180 int ret;
181
182 if (vss == NULL)
183  return NULL;
184
[4206]185 memset(&(vss->info), 0, sizeof(vss->info));
[4174]186
[4206]187 vss->info.rate     = rate;
188 vss->info.channels = channels;
189 vss->info.codec    = codec;
190 vss->info.bits     = bits;
[4174]191
[4206]192 ret = roar_vs_stream(vss, &(vss->info), dir, error);
[4174]193
194 if (ret == -1) {
195  roar_vs_close(vss, ROAR_VS_TRUE, NULL);
196  return NULL;
197 }
198
199 return vss;
200}
201
202int roar_vs_close(roar_vs_t * vss, int killit, int * error) {
[4178]203 if ( killit != ROAR_VS_TRUE && killit != ROAR_VS_FALSE ) {
204  _seterr(ROAR_ERROR_UNKNOWN);
205  return -1;
206 }
207
[4260]208 _ckvss(-1);
209
[4174]210 if ( vss->flags & FLAG_STREAM ) {
[4178]211  if ( killit == ROAR_VS_TRUE ) {
[4174]212   roar_kick(vss->con, ROAR_OT_STREAM, roar_stream_get_id(&(vss->stream)));
213  }
214
215  roar_vio_close(&(vss->vio));
216 }
217
218 if ( vss->con == &(vss->con_store) ) {
219  roar_disconnect(vss->con);
220 }
221
222 roar_mm_free(vss);
223 return 0;
224}
225
226ssize_t roar_vs_write(roar_vs_t * vss, const void * buf, size_t len, int * error) {
227 ssize_t ret;
228
[4260]229 _ckvss(-1);
230
[4174]231 if ( !(vss->flags & FLAG_STREAM) ) {
232  _seterr(ROAR_ERROR_INVAL);
233  return -1;
234 }
235
[4186]236 _initerr();
237
[4174]238 ret = roar_vio_write(&(vss->vio), (void*)buf, len);
239
240 if ( ret == -1 ) {
[4199]241#ifdef EAGAIN
242  if ( errno == EAGAIN )
243   return 0;
244#endif
245
246#ifdef EWOULDBLOCK
247  if ( errno == EWOULDBLOCK )
248   return 0;
249#endif
250
[4186]251  _seterrre();
[4206]252 } else {
253  vss->writec += ret;
[4174]254 }
255
256 return ret;
257}
258
259ssize_t roar_vs_read (roar_vs_t * vss,       void * buf, size_t len, int * error) {
260 ssize_t ret;
261
[4260]262 _ckvss(-1);
263
[4174]264 if ( !(vss->flags & FLAG_STREAM) ) {
265  _seterr(ROAR_ERROR_INVAL);
266  return -1;
267 }
268
[4186]269 _initerr();
270
[4174]271 ret = roar_vio_read(&(vss->vio), buf, len);
272
273 if ( ret == -1 ) {
[4186]274  _seterrre();
[4206]275 } else {
276  vss->readc += ret;
[4174]277 }
278
279 return ret;
280}
281
[4175]282int     roar_vs_sync (roar_vs_t * vss, int wait, int * error) {
[4579]283 struct roar_event waits, triggered;
284
[4260]285 _ckvss(-1);
286
[4175]287 if ( !(vss->flags & FLAG_STREAM) ) {
288  _seterr(ROAR_ERROR_INVAL);
289  return -1;
290 }
291
[4579]292 if ( wait != ROAR_VS_NOWAIT && wait != ROAR_VS_WAIT ) {
[4175]293  _seterr(ROAR_ERROR_INVAL);
294  return -1;
295 }
296
[4186]297 _initerr();
298
299 if ( roar_vio_sync(&(vss->vio)) == -1 ) {
300  _seterrre();
301  return -1;
302 }
[4175]303
[4579]304 if ( wait == ROAR_VS_WAIT ) {
305  memset(&waits, 0, sizeof(waits));
306  waits.event       = ROAR_OE_STREAM_XRUN;
307  waits.emitter     = -1;
308  waits.target      = roar_stream_get_id(&(vss->stream));
309  waits.target_type = ROAR_OT_STREAM;
310
311  if ( roar_wait(vss->con, &triggered, &waits, 1) == -1 ) {
312   _seterrre();
313   return -1;
314  }
315 }
316
[4175]317 return 0;
318}
319
320int     roar_vs_blocking (roar_vs_t * vss, int val, int * error) {
321 int old = -1;
322
[4260]323 _ckvss(-1);
324
[4175]325  if ( !(vss->flags & FLAG_STREAM) ) {
326  _seterr(ROAR_ERROR_INVAL);
327  return -1;
328 }
329
330 old = vss->flags & FLAG_NONBLOCK ? ROAR_VS_FALSE : ROAR_VS_TRUE;
331
[4186]332 _initerr();
333
[4175]334 switch (val) {
335  case ROAR_VS_TRUE:
336    if ( roar_vio_nonblock(&(vss->vio), ROAR_SOCKET_BLOCK) == -1 ) {
[4186]337     _seterrre();
[4175]338     return -1;
339    }
340    vss->flags |= FLAG_NONBLOCK;
341    vss->flags -= FLAG_NONBLOCK;
342    return old;
343   break;
344  case ROAR_VS_FALSE:
345    if ( roar_vio_nonblock(&(vss->vio), ROAR_SOCKET_NONBLOCK) == -1 ) {
[4186]346     _seterrre();
[4175]347     return -1;
348    }
349    vss->flags |= FLAG_NONBLOCK;
350    return old;
351   break;
352  case ROAR_VS_TOGGLE:
353    if ( old == ROAR_VS_TRUE ) {
354     return roar_vs_blocking(vss, ROAR_VS_FALSE, error);
355    } else {
356     return roar_vs_blocking(vss, ROAR_VS_TRUE, error);
357    }
358   break;
359  case ROAR_VS_ASK:
360    return old;
361   break;
362 }
363
364 _seterr(ROAR_ERROR_INVAL);
365 return -1;
366}
367
[4206]368static int _roar_vs_find_first_prim(roar_vs_t * vss) {
369 struct roar_stream stream;
370 struct roar_stream_info info;
371 int id[ROAR_STREAMS_MAX];
372 int num;
373 int i;
374
375 if ( vss->first_primid != -1 )
376  return vss->first_primid;
377
378 if ( vss->mixerid == -1 )
379  return -1;
380
381 if ( (num = roar_list_streams(vss->con, id, ROAR_STREAMS_MAX)) == -1 ) {
382  return -1;
383 }
384
385 for (i = 0; i < num; i++) {
386  if ( roar_get_stream(vss->con, &stream, id[i]) == -1 )
387   continue;
388
389  if ( stream.dir != ROAR_DIR_OUTPUT )
390   continue;
391
392  if ( roar_stream_get_info(vss->con, &stream, &info) == -1 )
393   continue;
394
395  if ( info.mixer == vss->mixerid ) {
396   vss->first_primid = id[i];
397   return id[i];
398  }
399 }
400
401 return -1;
402}
403
404ssize_t roar_vs_position(roar_vs_t * vss, int backend, int * error) {
405 struct roar_stream stream;
406 struct roar_stream      out_stream;
407 struct roar_stream_info out_info;
408 size_t offset;
409
[4260]410 _ckvss(-1);
411
[4206]412 if ( !(vss->flags & FLAG_STREAM) ) {
413  _seterr(ROAR_ERROR_INVAL);
414  return -1;
415 }
416
417 _initerr();
418
419 if ( roar_get_stream(vss->con, &stream, roar_stream_get_id(&(vss->stream))) == -1 ) {
420  _seterrre();
421  return -1;
422 }
423
424 switch (backend) {
425  case ROAR_VS_BACKEND_NONE:
426    return stream.pos;
427   break;
428  case ROAR_VS_BACKEND_FIRST:
429   // _roar_vs_find_first_prim(vss);
430    if ( vss->first_primid == -1 ) {
431     _seterr(ROAR_ERROR_UNKNOWN);
432     return -1;
433    }
434
435    roar_stream_new_by_id(&out_stream, vss->first_primid);
436
437    if ( roar_stream_get_info(vss->con, &out_stream, &out_info) == -1 ) {
438     _seterrre();
439     return -1;
440    }
441
442    offset  = out_info.delay * vss->info.rate;
443    offset /= 1000000;
444
445    return stream.pos + offset;
446   break;
447  default:
448    _seterr(ROAR_ERROR_NOTSUP);
449    return -1;
450   break;
451 }
452
[4186]453 _seterr(ROAR_ERROR_NOSYS);
[4175]454 return -1;
455}
456
[4206]457roar_mus_t roar_vs_latency(roar_vs_t * vss, int backend, int * error) {
458 ssize_t pos  = roar_vs_position(vss, backend, error);
459 ssize_t bps;  // byte per sample
460 size_t  lioc; // local IO (byte) counter
461 size_t  lpos; // local possition
462 roar_mus_t  lag;
463
[4215]464 _initerr();
465
[4260]466 _ckvss(-1);
467
[4215]468 if (pos == -1) {
469  _seterrre();
470  return 0;
471 }
[4206]472
473 if ( !(vss->flags & FLAG_STREAM) ) {
474  _seterr(ROAR_ERROR_INVAL);
[4213]475  return 0;
[4206]476 }
477
478 if ( vss->writec == 0 ) {
479  lioc = vss->readc;
480 } else {
481  lioc = vss->writec;
482 }
483
484 bps = roar_info2samplesize(&(vss->info));
485
486 if ( bps == -1 ) {
487  _seterrre();
[4213]488  return 0;
[4206]489 }
490
491 lpos = lioc / bps;
492
493 lag = (roar_mus_t)lpos - (roar_mus_t)pos;
494
495 // we now have the lag in frames
496 // return value are ms
497 // so we need to multiply with 1s/ms and
498 // multiply by 1/rate
499
500 lag *= 1000000; // 1s/ms
501 lag /= vss->info.rate;
502
[4213]503 if ( lag == 0 ) {
504  _seterr(ROAR_ERROR_NONE);
505 }
506
[4206]507 return lag;
508}
509
[4175]510static int roar_vs_flag(roar_vs_t * vss, int flag, int val, int * error) {
511 struct roar_stream_info info;
512 int old = -1;
513
[4260]514 _ckvss(-1);
515
[4175]516 if ( !(vss->flags & FLAG_STREAM) ) {
517  _seterr(ROAR_ERROR_INVAL);
518  return -1;
519 }
520
521 if ( val != ROAR_VS_ASK )
522  old = roar_vs_flag(vss, flag, ROAR_VS_ASK, error);
523
[4186]524 _initerr();
525
[4175]526 switch (val) {
527  case ROAR_VS_TRUE:
528  case ROAR_VS_FALSE:
529    if ( roar_stream_set_flags(vss->con, &(vss->stream), flag,
530                               val == ROAR_VS_TRUE ? ROAR_SET_FLAG : ROAR_RESET_FLAG) == -1 ) {
[4186]531     _seterrre();
[4175]532     return -1;
533    }
534    return old;
535   break;
536  case ROAR_VS_TOGGLE:
537    return roar_vs_flag(vss, flag, old == ROAR_VS_TRUE ? ROAR_VS_FALSE : ROAR_VS_TRUE, error);
538   break;
539  case ROAR_VS_ASK:
540    if ( roar_stream_get_info(vss->con, &(vss->stream), &info) == -1 ) {
[4186]541     _seterrre();
[4175]542     return -1;
543    }
544    return info.flags & flag ? ROAR_VS_TRUE : ROAR_VS_FALSE;
545   break;
546 }
547
[4187]548 _seterr(ROAR_ERROR_INVAL);
[4175]549 return -1;
550}
551
552int     roar_vs_pause(roar_vs_t * vss, int val, int * error) {
553 return roar_vs_flag(vss, ROAR_FLAG_PAUSE, val, error);
554}
555
556int     roar_vs_mute (roar_vs_t * vss, int val, int * error) {
557 return roar_vs_flag(vss, ROAR_FLAG_MUTE, val, error);
558}
559
560static int roar_vs_volume (roar_vs_t * vss, float * c, size_t channels, int * error) {
561 struct roar_mixer_settings mixer;
562 size_t i;
[4179]563 register float s;
[4182]564 int oldchannels;
565 int handled;
[4175]566
[4260]567 _ckvss(-1);
568
[4175]569 if ( !(vss->flags & FLAG_STREAM) ) {
570  _seterr(ROAR_ERROR_INVAL);
571  return -1;
572 }
573
574 if ( channels > ROAR_MAX_CHANNELS ) {
575  _seterr(ROAR_ERROR_INVAL);
576  return -1;
577 }
578
[4186]579 _initerr();
580
[4182]581 if ( roar_get_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, &oldchannels) == -1 ) {
[4186]582  _seterrre();
[4182]583  return -1;
584 }
585
[4179]586 for (i = 0; i < channels; i++) {
587  s = c[i] * 65535.0;
588  if ( s > 66190.0 || s < -655.0 ) {
589   _seterr(ROAR_ERROR_RANGE);
590   return -1;
591  } else if ( s > 65535.0 ) {
592   s = 65535.0;
593  } else if ( s <     0.0 ) {
594   s = 0.0;
595  }
596  mixer.mixer[i] = s;
597 }
[4175]598
599 mixer.scale = 65535;
[4182]600
601 if ( channels != oldchannels ) {
602  handled = 0;
603  switch (oldchannels) {
604   case 1:
605     if ( channels == 2 ) {
606      mixer.mixer[0] = (mixer.mixer[0] + mixer.mixer[1]) / 2;
607      handled = 1;
608     }
609    break;
610   case 2:
611     if ( channels == 1 ) {
612      mixer.mixer[1] = mixer.mixer[0];
613      handled = 1;
614     }
615    break;
616   case 4:
617     if ( channels == 1 ) {
618      mixer.mixer[1] = mixer.mixer[0];
619      mixer.mixer[2] = mixer.mixer[0];
620      mixer.mixer[3] = mixer.mixer[0];
621      handled = 1;
622     } else if ( channels == 2 ) {
623      mixer.mixer[2] = mixer.mixer[0];
624      mixer.mixer[3] = mixer.mixer[1];
625      handled = 1;
626     }
627    break;
628  }
629  if ( handled ) {
630   channels = oldchannels;
631  } else {
632   _seterr(ROAR_ERROR_INVAL);
633   return -1;
634  }
635 }
[4175]636
637 if ( roar_set_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, channels) == -1 ) {
[4186]638  _seterrre();
[4175]639  return -1;
640 }
641
642 return 0;
643}
644
645int     roar_vs_volume_mono   (roar_vs_t * vss, float c, int * error) {
646 return roar_vs_volume(vss, &c, 1, error);
647}
648
649int     roar_vs_volume_stereo (roar_vs_t * vss, float l, float r, int * error) {
650 float c[2] = {l, r};
651 return roar_vs_volume(vss, c, 2, error);
652}
653
654int     roar_vs_volume_get    (roar_vs_t * vss, float * l, float * r, int * error) {
655 struct roar_mixer_settings mixer;
656 int channels;
657
658 if ( vss == NULL || l == NULL || r == NULL ) {
659  _seterr(ROAR_ERROR_INVAL);
660  return -1;
661 }
662
663 if ( !(vss->flags & FLAG_STREAM) ) {
664  _seterr(ROAR_ERROR_INVAL);
665  return -1;
666 }
667
[4186]668 _initerr();
669
[4175]670 if ( roar_get_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, &channels) == -1 ) {
[4186]671  _seterrre();
[4175]672  return -1;
673 }
674
675 if ( channels == 1 )
676  mixer.mixer[1] = mixer.mixer[0];
677
678 *l = mixer.mixer[0] / (float)mixer.scale;
679 *r = mixer.mixer[1] / (float)mixer.scale;
680
681 return 0;
682}
683
[4176]684int     roar_vs_meta          (roar_vs_t * vss, struct roar_keyval * kv, size_t len, int * error) {
685 struct roar_meta meta;
686 size_t i;
687 int type;
[4180]688 int ret = 0;
[4176]689
[4260]690 _ckvss(-1);
691
[4176]692 if ( !(vss->flags & FLAG_STREAM) ) {
693  _seterr(ROAR_ERROR_INVAL);
694  return -1;
695 }
696
697 meta.type   = ROAR_META_TYPE_NONE;
698 meta.key[0] = 0;
699 meta.value  = NULL;
700
[4186]701 _initerr();
[4176]702
[4180]703 if ( roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_CLEAR, &meta) == -1 ) {
[4186]704  _seterrre();
[4180]705  ret = -1;
706 }
[4176]707
708 for (i = 0; i < len; i++) {
709  type = roar_meta_inttype(kv[i].key);
710  meta.type  = type;
711  meta.value = kv[i].value;
712
[4180]713  if ( roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_ADD, &meta) == -1 ) {
[4186]714   _seterrre();
[4180]715   ret = -1;
716  }
[4176]717 }
718
719 meta.type   = ROAR_META_TYPE_NONE;
720 meta.key[0] = 0;
721 meta.value  = NULL;
[4180]722 if ( roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_FINALIZE, &meta) == -1 ) {
[4186]723  _seterrre();
[4180]724  ret = -1;
725 }
[4176]726
[4180]727 return ret;
[4176]728}
[4174]729
[4212]730int     roar_vs_role          (roar_vs_t * vss, int role, int * error) {
[4260]731 _ckvss(-1);
732
[4212]733 if ( !(vss->flags & FLAG_STREAM) ) {
734  _seterr(ROAR_ERROR_INVAL);
735  return -1;
736 }
737
738 _initerr();
739
740 if ( roar_stream_set_role(vss->con, &(vss->stream), role) == -1 ) {
741  _seterrre();
742  return -1;
743 }
744
745 return 0;
746}
747
[4183]748struct roar_connection * roar_vs_connection_obj(roar_vs_t * vss, int * error) {
[4260]749 _ckvss(NULL);
750
[4183]751 return vss->con;
752}
753
754struct roar_stream     * roar_vs_stream_obj    (roar_vs_t * vss, int * error) {
[4260]755 _ckvss(NULL);
756
[4183]757 if ( !(vss->flags & FLAG_STREAM) ) {
758  _seterr(ROAR_ERROR_INVAL);
[4186]759  return NULL;
[4183]760 }
761
762 return &(vss->stream);
763}
764
765struct roar_vio_calls  * roar_vs_vio_obj       (roar_vs_t * vss, int * error) {
[4260]766 _ckvss(NULL);
767
[4183]768 if ( !(vss->flags & FLAG_STREAM) ) {
769  _seterr(ROAR_ERROR_INVAL);
[4186]770  return NULL;
[4183]771 }
772
773 return &(vss->vio);
774}
775
[4173]776//ll
Note: See TracBrowser for help on using the repository browser.