source: roaraudio/libroar/vs.c @ 4180:4619bbe707d8

Last change on this file since 4180:4619bbe707d8 was 4180:4619bbe707d8, checked in by phi, 14 years ago

add error handling for setting meta data

File size: 10.5 KB
Line 
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
38#define FLAG_NONE     0x0000
39#define FLAG_STREAM   0x0001
40#define FLAG_NONBLOCK 0x0002
41
42#define _seterr(x) do { if ( error != NULL ) *error = (x); } while(0)
43
44struct roar_vs {
45 int flags;
46 struct roar_connection con_store;
47 struct roar_connection * con;
48 struct roar_stream       stream;
49 struct roar_vio_calls    vio;
50};
51
52const char * roar_vs_strerr(int error) {
53 const struct {
54  int err;
55  const char * msg;
56 } msgs[] = {
57  {ROAR_ERROR_NONE,    "none"},
58  {ROAR_ERROR_PERM,    "perm"},
59  {ROAR_ERROR_NOENT,   "noent"},
60  {ROAR_ERROR_BADMSG,  "badmsg"},
61  {ROAR_ERROR_BUSY,    "busy"},
62  {ROAR_ERROR_CONNREFUSED, "connrefused"},
63  {ROAR_ERROR_NOSYS,   "nosys"},
64  {ROAR_ERROR_NOTSUP,  "notsup"},
65  {ROAR_ERROR_PIPE,    "pipe"},
66  {ROAR_ERROR_PROTO,   "proto"},
67  {ROAR_ERROR_RANGE,   "range"},
68  {ROAR_ERROR_MSGSIZE, "msgsize"},
69  {ROAR_ERROR_NOMEM,   "nomem"},
70  {ROAR_ERROR_INVAL,   "inval"},
71  {-1, NULL}
72 };
73 int i;
74
75 for (i = 0; msgs[i].msg != NULL; i++)
76  if ( msgs[i].err == error )
77   return msgs[i].msg;
78
79 return "(unknown)";
80}
81
82static roar_vs_t * roar_vs_init(int * error) {
83 roar_vs_t * vss = roar_mm_malloc(sizeof(roar_vs_t));
84
85 if ( vss == NULL ) {
86  _seterr(ROAR_ERROR_NOMEM);
87  return NULL;
88 }
89
90 memset(vss, 0, sizeof(roar_vs_t));
91
92 return vss;
93}
94
95roar_vs_t * roar_vs_new_from_con(struct roar_connection * con, int * error) {
96 roar_vs_t * vss = roar_vs_init(error);
97
98 if ( vss == NULL )
99  return NULL;
100
101 vss->con = con;
102
103 return vss;
104}
105
106roar_vs_t * roar_vs_new(const char * server, const char * name, int * error) {
107 roar_vs_t * vss = roar_vs_init(error);
108 int ret;
109
110 if ( vss == NULL )
111  return NULL;
112
113 vss->con = &(vss->con_store);
114
115 ret = roar_simple_connect(vss->con, (char*)server, (char*)name);
116
117 if ( ret == -1 ) {
118  roar_vs_close(vss, ROAR_VS_TRUE, NULL);
119  _seterr(ROAR_ERROR_UNKNOWN);
120  return NULL;
121 }
122
123 return vss;
124}
125
126int roar_vs_stream(roar_vs_t * vss, const struct roar_audio_info * info, int dir, int * error) {
127 int ret;
128
129 if ( vss->flags & FLAG_STREAM ) {
130  _seterr(ROAR_ERROR_INVAL);
131  return -1;
132 }
133
134 ret = roar_vio_simple_new_stream_obj(&(vss->vio), vss->con, &(vss->stream),
135                                      info->rate, info->channels, info->bits, info->codec,
136                                      dir
137                                     );
138
139 if ( ret == -1 ) {
140  _seterr(ROAR_ERROR_UNKNOWN);
141  return -1;
142 }
143
144 vss->flags |= FLAG_STREAM;
145
146 return 0;
147}
148
149roar_vs_t * roar_vs_new_simple(const char * server, const char * name, int rate, int channels, int codec, int bits, int dir, int * error) {
150 roar_vs_t * vss = roar_vs_new(server, name, error);
151 struct roar_audio_info info;
152 int ret;
153
154 if (vss == NULL)
155  return NULL;
156
157 memset(&info, 0, sizeof(info));
158
159 info.rate     = rate;
160 info.channels = channels;
161 info.codec    = codec;
162 info.bits     = bits;
163
164 ret = roar_vs_stream(vss, &info, dir, error);
165
166 if (ret == -1) {
167  roar_vs_close(vss, ROAR_VS_TRUE, NULL);
168  return NULL;
169 }
170
171 return vss;
172}
173
174int roar_vs_close(roar_vs_t * vss, int killit, int * error) {
175 if ( killit != ROAR_VS_TRUE && killit != ROAR_VS_FALSE ) {
176  _seterr(ROAR_ERROR_UNKNOWN);
177  return -1;
178 }
179
180 if ( vss->flags & FLAG_STREAM ) {
181  if ( killit == ROAR_VS_TRUE ) {
182   roar_kick(vss->con, ROAR_OT_STREAM, roar_stream_get_id(&(vss->stream)));
183  }
184
185  roar_vio_close(&(vss->vio));
186 }
187
188 if ( vss->con == &(vss->con_store) ) {
189  roar_disconnect(vss->con);
190 }
191
192 roar_mm_free(vss);
193 return 0;
194}
195
196ssize_t roar_vs_write(roar_vs_t * vss, const void * buf, size_t len, int * error) {
197 ssize_t ret;
198
199 if ( !(vss->flags & FLAG_STREAM) ) {
200  _seterr(ROAR_ERROR_INVAL);
201  return -1;
202 }
203
204 ret = roar_vio_write(&(vss->vio), (void*)buf, len);
205
206 if ( ret == -1 ) {
207  _seterr(ROAR_ERROR_UNKNOWN);
208 }
209
210 return ret;
211}
212
213ssize_t roar_vs_read (roar_vs_t * vss,       void * buf, size_t len, int * error) {
214 ssize_t ret;
215
216 if ( !(vss->flags & FLAG_STREAM) ) {
217  _seterr(ROAR_ERROR_INVAL);
218  return -1;
219 }
220
221 ret = roar_vio_read(&(vss->vio), buf, len);
222
223 if ( ret == -1 ) {
224  _seterr(ROAR_ERROR_UNKNOWN);
225 }
226
227 return ret;
228}
229
230int     roar_vs_sync (roar_vs_t * vss, int wait, int * error) {
231 if ( !(vss->flags & FLAG_STREAM) ) {
232  _seterr(ROAR_ERROR_INVAL);
233  return -1;
234 }
235
236 if ( wait != ROAR_VS_NOWAIT ) {
237  _seterr(ROAR_ERROR_INVAL);
238  return -1;
239 }
240
241 roar_vio_sync(&(vss->vio));
242
243 return 0;
244}
245
246int     roar_vs_blocking (roar_vs_t * vss, int val, int * error) {
247 int old = -1;
248
249  if ( !(vss->flags & FLAG_STREAM) ) {
250  _seterr(ROAR_ERROR_INVAL);
251  return -1;
252 }
253
254 old = vss->flags & FLAG_NONBLOCK ? ROAR_VS_FALSE : ROAR_VS_TRUE;
255
256 switch (val) {
257  case ROAR_VS_TRUE:
258    if ( roar_vio_nonblock(&(vss->vio), ROAR_SOCKET_BLOCK) == -1 ) {
259     _seterr(ROAR_ERROR_UNKNOWN);
260     return -1;
261    }
262    vss->flags |= FLAG_NONBLOCK;
263    vss->flags -= FLAG_NONBLOCK;
264    return old;
265   break;
266  case ROAR_VS_FALSE:
267    if ( roar_vio_nonblock(&(vss->vio), ROAR_SOCKET_NONBLOCK) == -1 ) {
268     _seterr(ROAR_ERROR_UNKNOWN);
269     return -1;
270    }
271    vss->flags |= FLAG_NONBLOCK;
272    return old;
273   break;
274  case ROAR_VS_TOGGLE:
275    if ( old == ROAR_VS_TRUE ) {
276     return roar_vs_blocking(vss, ROAR_VS_FALSE, error);
277    } else {
278     return roar_vs_blocking(vss, ROAR_VS_TRUE, error);
279    }
280   break;
281  case ROAR_VS_ASK:
282    return old;
283   break;
284 }
285
286 _seterr(ROAR_ERROR_INVAL);
287 return -1;
288}
289
290ssize_t roar_vs_latency(roar_vs_t * vss, int backend, int * error) {
291 _seterr(ROAR_ERROR_NOTSUP);
292 return -1;
293}
294
295static int roar_vs_flag(roar_vs_t * vss, int flag, int val, int * error) {
296 struct roar_stream_info info;
297 int old = -1;
298
299 if ( !(vss->flags & FLAG_STREAM) ) {
300  _seterr(ROAR_ERROR_INVAL);
301  return -1;
302 }
303
304 if ( val != ROAR_VS_ASK )
305  old = roar_vs_flag(vss, flag, ROAR_VS_ASK, error);
306
307 switch (val) {
308  case ROAR_VS_TRUE:
309  case ROAR_VS_FALSE:
310    if ( roar_stream_set_flags(vss->con, &(vss->stream), flag,
311                               val == ROAR_VS_TRUE ? ROAR_SET_FLAG : ROAR_RESET_FLAG) == -1 ) {
312     _seterr(ROAR_ERROR_UNKNOWN);
313     return -1;
314    }
315    return old;
316   break;
317  case ROAR_VS_TOGGLE:
318    return roar_vs_flag(vss, flag, old == ROAR_VS_TRUE ? ROAR_VS_FALSE : ROAR_VS_TRUE, error);
319   break;
320  case ROAR_VS_ASK:
321    if ( roar_stream_get_info(vss->con, &(vss->stream), &info) == -1 ) {
322     _seterr(ROAR_ERROR_UNKNOWN);
323     return -1;
324    }
325    return info.flags & flag ? ROAR_VS_TRUE : ROAR_VS_FALSE;
326   break;
327 }
328
329 _seterr(ROAR_ERROR_NOTSUP);
330 return -1;
331}
332
333int     roar_vs_pause(roar_vs_t * vss, int val, int * error) {
334 return roar_vs_flag(vss, ROAR_FLAG_PAUSE, val, error);
335}
336
337int     roar_vs_mute (roar_vs_t * vss, int val, int * error) {
338 return roar_vs_flag(vss, ROAR_FLAG_MUTE, val, error);
339}
340
341static int roar_vs_volume (roar_vs_t * vss, float * c, size_t channels, int * error) {
342 struct roar_mixer_settings mixer;
343 size_t i;
344 register float s;
345
346 if ( !(vss->flags & FLAG_STREAM) ) {
347  _seterr(ROAR_ERROR_INVAL);
348  return -1;
349 }
350
351 if ( channels > ROAR_MAX_CHANNELS ) {
352  _seterr(ROAR_ERROR_INVAL);
353  return -1;
354 }
355
356 for (i = 0; i < channels; i++) {
357  s = c[i] * 65535.0;
358  if ( s > 66190.0 || s < -655.0 ) {
359   _seterr(ROAR_ERROR_RANGE);
360   return -1;
361  } else if ( s > 65535.0 ) {
362   s = 65535.0;
363  } else if ( s <     0.0 ) {
364   s = 0.0;
365  }
366  mixer.mixer[i] = s;
367 }
368
369 mixer.scale = 65535;
370 mixer.rpg_mul = 1;
371 mixer.rpg_div = 1;
372
373 if ( roar_set_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, channels) == -1 ) {
374  _seterr(ROAR_ERROR_UNKNOWN);
375  return -1;
376 }
377
378 return 0;
379}
380
381int     roar_vs_volume_mono   (roar_vs_t * vss, float c, int * error) {
382 return roar_vs_volume(vss, &c, 1, error);
383}
384
385int     roar_vs_volume_stereo (roar_vs_t * vss, float l, float r, int * error) {
386 float c[2] = {l, r};
387 return roar_vs_volume(vss, c, 2, error);
388}
389
390int     roar_vs_volume_get    (roar_vs_t * vss, float * l, float * r, int * error) {
391 struct roar_mixer_settings mixer;
392 int channels;
393
394 if ( vss == NULL || l == NULL || r == NULL ) {
395  _seterr(ROAR_ERROR_INVAL);
396  return -1;
397 }
398
399 if ( !(vss->flags & FLAG_STREAM) ) {
400  _seterr(ROAR_ERROR_INVAL);
401  return -1;
402 }
403
404 if ( roar_get_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, &channels) == -1 ) {
405  _seterr(ROAR_ERROR_UNKNOWN);
406  return -1;
407 }
408
409 if ( channels == 1 )
410  mixer.mixer[1] = mixer.mixer[0];
411
412 *l = mixer.mixer[0] / (float)mixer.scale;
413 *r = mixer.mixer[1] / (float)mixer.scale;
414
415 return 0;
416}
417
418int     roar_vs_meta          (roar_vs_t * vss, struct roar_keyval * kv, size_t len, int * error) {
419 struct roar_meta meta;
420 size_t i;
421 int type;
422 int ret = 0;
423
424 if ( !(vss->flags & FLAG_STREAM) ) {
425  _seterr(ROAR_ERROR_INVAL);
426  return -1;
427 }
428
429 meta.type   = ROAR_META_TYPE_NONE;
430 meta.key[0] = 0;
431 meta.value  = NULL;
432
433 // TODO: add error hadnling here.
434
435 if ( roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_CLEAR, &meta) == -1 ) {
436  _seterr(ROAR_ERROR_UNKNOWN);
437  ret = -1;
438 }
439
440 for (i = 0; i < len; i++) {
441  type = roar_meta_inttype(kv[i].key);
442  meta.type  = type;
443  meta.value = kv[i].value;
444
445  if ( roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_ADD, &meta) == -1 ) {
446   _seterr(ROAR_ERROR_UNKNOWN);
447   ret = -1;
448  }
449 }
450
451 meta.type   = ROAR_META_TYPE_NONE;
452 meta.key[0] = 0;
453 meta.value  = NULL;
454 if ( roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_FINALIZE, &meta) == -1 ) {
455  _seterr(ROAR_ERROR_UNKNOWN);
456  ret = -1;
457 }
458
459 return ret;
460}
461
462//ll
Note: See TracBrowser for help on using the repository browser.