source: roaraudio/libroar/vs.c @ 4175:c8a616dfbb8a

Last change on this file since 4175:c8a616dfbb8a was 4175:c8a616dfbb8a, checked in by phi, 14 years ago

some very basic stream operations

File size: 9.3 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(1)
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 ( vss->flags & FLAG_STREAM ) {
176  if ( killit ) {
177   roar_kick(vss->con, ROAR_OT_STREAM, roar_stream_get_id(&(vss->stream)));
178  }
179
180  roar_vio_close(&(vss->vio));
181 }
182
183 if ( vss->con == &(vss->con_store) ) {
184  roar_disconnect(vss->con);
185 }
186
187 roar_mm_free(vss);
188 return 0;
189}
190
191ssize_t roar_vs_write(roar_vs_t * vss, const void * buf, size_t len, int * error) {
192 ssize_t ret;
193
194 if ( !(vss->flags & FLAG_STREAM) ) {
195  _seterr(ROAR_ERROR_INVAL);
196  return -1;
197 }
198
199 ret = roar_vio_write(&(vss->vio), (void*)buf, len);
200
201 if ( ret == -1 ) {
202  _seterr(ROAR_ERROR_UNKNOWN);
203 }
204
205 return ret;
206}
207
208ssize_t roar_vs_read (roar_vs_t * vss,       void * buf, size_t len, int * error) {
209 ssize_t ret;
210
211 if ( !(vss->flags & FLAG_STREAM) ) {
212  _seterr(ROAR_ERROR_INVAL);
213  return -1;
214 }
215
216 ret = roar_vio_read(&(vss->vio), buf, len);
217
218 if ( ret == -1 ) {
219  _seterr(ROAR_ERROR_UNKNOWN);
220 }
221
222 return ret;
223}
224
225int     roar_vs_sync (roar_vs_t * vss, int wait, int * error) {
226 if ( !(vss->flags & FLAG_STREAM) ) {
227  _seterr(ROAR_ERROR_INVAL);
228  return -1;
229 }
230
231 if ( wait != ROAR_VS_NOWAIT ) {
232  _seterr(ROAR_ERROR_INVAL);
233  return -1;
234 }
235
236 roar_vio_sync(&(vss->vio));
237
238 return 0;
239}
240
241int     roar_vs_blocking (roar_vs_t * vss, int val, int * error) {
242 int old = -1;
243
244  if ( !(vss->flags & FLAG_STREAM) ) {
245  _seterr(ROAR_ERROR_INVAL);
246  return -1;
247 }
248
249 old = vss->flags & FLAG_NONBLOCK ? ROAR_VS_FALSE : ROAR_VS_TRUE;
250
251 switch (val) {
252  case ROAR_VS_TRUE:
253    if ( roar_vio_nonblock(&(vss->vio), ROAR_SOCKET_BLOCK) == -1 ) {
254     _seterr(ROAR_ERROR_UNKNOWN);
255     return -1;
256    }
257    vss->flags |= FLAG_NONBLOCK;
258    vss->flags -= FLAG_NONBLOCK;
259    return old;
260   break;
261  case ROAR_VS_FALSE:
262    if ( roar_vio_nonblock(&(vss->vio), ROAR_SOCKET_NONBLOCK) == -1 ) {
263     _seterr(ROAR_ERROR_UNKNOWN);
264     return -1;
265    }
266    vss->flags |= FLAG_NONBLOCK;
267    return old;
268   break;
269  case ROAR_VS_TOGGLE:
270    if ( old == ROAR_VS_TRUE ) {
271     return roar_vs_blocking(vss, ROAR_VS_FALSE, error);
272    } else {
273     return roar_vs_blocking(vss, ROAR_VS_TRUE, error);
274    }
275   break;
276  case ROAR_VS_ASK:
277    return old;
278   break;
279 }
280
281 _seterr(ROAR_ERROR_INVAL);
282 return -1;
283}
284
285// ....................
286ssize_t roar_vs_latency(roar_vs_t * vss, int backend, int * error) {
287 _seterr(ROAR_ERROR_NOTSUP);
288 return -1;
289}
290
291static int roar_vs_flag(roar_vs_t * vss, int flag, int val, int * error) {
292 struct roar_stream_info info;
293 int old = -1;
294
295 if ( !(vss->flags & FLAG_STREAM) ) {
296  _seterr(ROAR_ERROR_INVAL);
297  return -1;
298 }
299
300 if ( val != ROAR_VS_ASK )
301  old = roar_vs_flag(vss, flag, ROAR_VS_ASK, error);
302
303 switch (val) {
304  case ROAR_VS_TRUE:
305  case ROAR_VS_FALSE:
306    if ( roar_stream_set_flags(vss->con, &(vss->stream), flag,
307                               val == ROAR_VS_TRUE ? ROAR_SET_FLAG : ROAR_RESET_FLAG) == -1 ) {
308     _seterr(ROAR_ERROR_UNKNOWN);
309     return -1;
310    }
311    return old;
312   break;
313  case ROAR_VS_TOGGLE:
314    return roar_vs_flag(vss, flag, old == ROAR_VS_TRUE ? ROAR_VS_FALSE : ROAR_VS_TRUE, error);
315   break;
316  case ROAR_VS_ASK:
317    if ( roar_stream_get_info(vss->con, &(vss->stream), &info) == -1 ) {
318     _seterr(ROAR_ERROR_UNKNOWN);
319     return -1;
320    }
321    return info.flags & flag ? ROAR_VS_TRUE : ROAR_VS_FALSE;
322   break;
323 }
324
325 _seterr(ROAR_ERROR_NOTSUP);
326 return -1;
327}
328
329int     roar_vs_pause(roar_vs_t * vss, int val, int * error) {
330 return roar_vs_flag(vss, ROAR_FLAG_PAUSE, val, error);
331}
332
333int     roar_vs_mute (roar_vs_t * vss, int val, int * error) {
334 return roar_vs_flag(vss, ROAR_FLAG_MUTE, val, error);
335}
336
337static int roar_vs_volume (roar_vs_t * vss, float * c, size_t channels, int * error) {
338 struct roar_mixer_settings mixer;
339 size_t i;
340
341 if ( !(vss->flags & FLAG_STREAM) ) {
342  _seterr(ROAR_ERROR_INVAL);
343  return -1;
344 }
345
346 if ( channels > ROAR_MAX_CHANNELS ) {
347  _seterr(ROAR_ERROR_INVAL);
348  return -1;
349 }
350
351 for (i = 0; i < channels; i++)
352  mixer.mixer[i] = c[i] * 65535.0;
353
354 mixer.scale = 65535;
355 mixer.rpg_mul = 1;
356 mixer.rpg_div = 1;
357
358 if ( roar_set_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, channels) == -1 ) {
359  _seterr(ROAR_ERROR_UNKNOWN);
360  return -1;
361 }
362
363 return 0;
364}
365
366int     roar_vs_volume_mono   (roar_vs_t * vss, float c, int * error) {
367 return roar_vs_volume(vss, &c, 1, error);
368}
369
370int     roar_vs_volume_stereo (roar_vs_t * vss, float l, float r, int * error) {
371 float c[2] = {l, r};
372 return roar_vs_volume(vss, c, 2, error);
373}
374
375int     roar_vs_volume_get    (roar_vs_t * vss, float * l, float * r, int * error) {
376 struct roar_mixer_settings mixer;
377 int channels;
378
379 if ( vss == NULL || l == NULL || r == NULL ) {
380  _seterr(ROAR_ERROR_INVAL);
381  return -1;
382 }
383
384 if ( !(vss->flags & FLAG_STREAM) ) {
385  _seterr(ROAR_ERROR_INVAL);
386  return -1;
387 }
388
389 if ( roar_get_vol(vss->con, roar_stream_get_id(&(vss->stream)), &mixer, &channels) == -1 ) {
390  _seterr(ROAR_ERROR_UNKNOWN);
391  return -1;
392 }
393
394 if ( channels == 1 )
395  mixer.mixer[1] = mixer.mixer[0];
396
397 *l = mixer.mixer[0] / (float)mixer.scale;
398 *r = mixer.mixer[1] / (float)mixer.scale;
399
400 return 0;
401}
402
403int     roar_vs_meta          (roar_vs_t * vss, struct roar_keyval * kv, size_t len, int * error);
404
405//ll
Note: See TracBrowser for help on using the repository browser.