source: roaraudio/libroar/vs.c @ 4178:0ba2fd898d1b

Last change on this file since 4178:0ba2fd898d1b was 4178:0ba2fd898d1b, checked in by phi, 14 years ago

bugs fixed by maister

File size: 10.1 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
345 if ( !(vss->flags & FLAG_STREAM) ) {
346  _seterr(ROAR_ERROR_INVAL);
347  return -1;
348 }
349
350 if ( channels > ROAR_MAX_CHANNELS ) {
351  _seterr(ROAR_ERROR_INVAL);
352  return -1;
353 }
354
355 for (i = 0; i < channels; i++)
356  mixer.mixer[i] = c[i] * 65535.0;
357
358 mixer.scale = 65535;
359 mixer.rpg_mul = 1;
360 mixer.rpg_div = 1;
361
362 if ( roar_set_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, channels) == -1 ) {
363  _seterr(ROAR_ERROR_UNKNOWN);
364  return -1;
365 }
366
367 return 0;
368}
369
370int     roar_vs_volume_mono   (roar_vs_t * vss, float c, int * error) {
371 return roar_vs_volume(vss, &c, 1, error);
372}
373
374int     roar_vs_volume_stereo (roar_vs_t * vss, float l, float r, int * error) {
375 float c[2] = {l, r};
376 return roar_vs_volume(vss, c, 2, error);
377}
378
379int     roar_vs_volume_get    (roar_vs_t * vss, float * l, float * r, int * error) {
380 struct roar_mixer_settings mixer;
381 int channels;
382
383 if ( vss == NULL || l == NULL || r == NULL ) {
384  _seterr(ROAR_ERROR_INVAL);
385  return -1;
386 }
387
388 if ( !(vss->flags & FLAG_STREAM) ) {
389  _seterr(ROAR_ERROR_INVAL);
390  return -1;
391 }
392
393 if ( roar_get_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, &channels) == -1 ) {
394  _seterr(ROAR_ERROR_UNKNOWN);
395  return -1;
396 }
397
398 if ( channels == 1 )
399  mixer.mixer[1] = mixer.mixer[0];
400
401 *l = mixer.mixer[0] / (float)mixer.scale;
402 *r = mixer.mixer[1] / (float)mixer.scale;
403
404 return 0;
405}
406
407int     roar_vs_meta          (roar_vs_t * vss, struct roar_keyval * kv, size_t len, int * error) {
408 struct roar_meta meta;
409 size_t i;
410 int type;
411
412 if ( !(vss->flags & FLAG_STREAM) ) {
413  _seterr(ROAR_ERROR_INVAL);
414  return -1;
415 }
416
417 meta.type   = ROAR_META_TYPE_NONE;
418 meta.key[0] = 0;
419 meta.value  = NULL;
420
421 // TODO: add error hadnling here.
422
423 roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_CLEAR, &meta);
424
425 for (i = 0; i < len; i++) {
426  type = roar_meta_inttype(kv[i].key);
427  meta.type  = type;
428  meta.value = kv[i].value;
429
430  roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_ADD, &meta);
431 }
432
433 meta.type   = ROAR_META_TYPE_NONE;
434 meta.key[0] = 0;
435 meta.value  = NULL;
436 roar_stream_meta_set(vss->con, &(vss->stream), ROAR_META_MODE_FINALIZE, &meta);
437
438 return 0;
439}
440
441//ll
Note: See TracBrowser for help on using the repository browser.