source: roaraudio/libroarrsound/libroarrsound.c @ 3933:67466545a09e

Last change on this file since 3933:67466545a09e was 3933:67466545a09e, checked in by phi, 14 years ago

corrected use of ROAR_DBG()

File size: 10.8 KB
Line 
1//libroarrsound.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *  The code (may) include prototypes and comments (and maybe
6 *  other code fragements) from RSound.
7 *  They are copyrighted by Hans-Kristian 'maister' Arntzen.
8 *
9 *  This file is part of libroarrsound a part of RoarAudio,
10 *  a cross-platform sound system for both, home and professional use.
11 *  See README for details.
12 *
13 *  This file is free software; you can redistribute it and/or modify
14 *  it under the terms of the GNU General Public License version 3
15 *  as published by the Free Software Foundation.
16 *
17 *  RoarAudio is distributed in the hope that it will be useful,
18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 *  GNU General Public License for more details.
21 *
22 *  You should have received a copy of the GNU General Public License
23 *  along with this software; see the file COPYING.  If not, write to
24 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25 *
26 *  NOTE for everyone want's to change something and send patches:
27 *  read README and HACKING! There a addition information on
28 *  the license of this document you need to read before you send
29 *  any patches.
30 */
31
32#include "libroarrsound.h"
33
34static size_t libroarrsound_fmt2fs (enum rsd_format format) {
35 switch (format) {
36  case RSD_S16_LE:
37  case RSD_S16_BE:
38  case RSD_S16_NE:
39  case RSD_U16_LE:
40  case RSD_U16_BE:
41  case RSD_U16_NE:
42    return 16;
43   break;
44  case RSD_U8:
45  case RSD_S8:
46  case RSD_ALAW:
47  case RSD_MULAW:
48    return 8;
49   break;
50  default:
51    return 0;
52   break;
53 }
54}
55
56int rsd_init (rsound_t **rd) {
57 struct libroarrsound * self;
58
59 ROAR_DBG("rsd_init(rd=%p) = ?", rd);
60
61 if ( rd == NULL )
62  return -1;
63
64 self = roar_mm_malloc(sizeof(struct libroarrsound));
65
66 if ( self == NULL )
67  return -1;
68
69 memset(self, 0, sizeof(struct libroarrsound));
70
71 *rd = (rsound_t*)self;
72
73 self->rsound.conn.socket     = -1;
74 self->rsound.conn.ctl_socket = -1;
75 self->rsound.channels        = ROAR_CHANNELS_DEFAULT;
76 self->rsound.rate            = ROAR_RATE_DEFAULT;
77 self->rsound.format          = RSD_S16_LE;
78
79 strncpy(self->rsound.identity, "libroarrsound client", sizeof(self->rsound.identity) - 1);
80 self->rsound.identity[sizeof(self->rsound.identity)-1] = 0;
81
82 return 0;
83}
84
85/* Frees an rsound_t struct. */
86int rsd_free (rsound_t *rd) {
87 struct libroarrsound * self = (struct libroarrsound *)rd;
88 int ret = 0;
89
90 if ( self == NULL )
91  return -1;
92
93 if ( self->flags & LIBROARRSOUND_FLAGS_CONNECTED )
94  if ( roar_disconnect(&(self->con)) == -1 )
95   ret = -1;
96
97 if ( self->flags & LIBROARRSOUND_FLAGS_STREAMING )
98  if ( roar_vio_close(&(self->vio)) == -1 )
99   ret = -1;
100
101 if ( self->rsound.host != NULL )
102  roar_mm_free(self->rsound.host);
103
104 if ( self->rsound.port != NULL )
105  roar_mm_free(self->rsound.port);
106
107 roar_mm_free(self);
108
109 return ret;
110}
111
112int rsd_set_param (rsound_t *rd, enum rsd_settings option, void* param) {
113 struct libroarrsound * self = (struct libroarrsound *)rd;
114
115 ROAR_DBG("rsd_set_param(rd=%p, option=%i, param=%p) = ?", rd, option, param);
116
117 if ( self == NULL || param == NULL )
118  return -1;
119
120 switch (option) {
121  // connection settings:
122  case RSD_HOST:
123    if ( self->rsound.host != NULL )
124     roar_mm_free(self->rsound.host);
125
126    self->rsound.host = roar_mm_strdup(param);
127   break;
128  case RSD_PORT:
129    if ( self->rsound.port != NULL )
130     roar_mm_free(self->rsound.port);
131
132    self->rsound.port = roar_mm_strdup(param);
133   break;
134#ifdef RSD_IDENTITY
135  case RSD_IDENTITY:
136    strncpy(self->rsound.identity, param, sizeof(self->rsound.identity) - 1);
137    self->rsound.identity[sizeof(self->rsound.identity)-1] = 0;
138   break;
139#endif
140  // stream settings:
141  case RSD_SAMPLERATE:
142    self->rsound.rate = *(int*)param;
143   break;
144  case RSD_CHANNELS:
145    self->rsound.channels = *(int*)param;
146   break;
147  case RSD_FORMAT:
148    self->rsound.format = *(int*)param;
149    self->rsound.framesize = libroarrsound_fmt2fs(self->rsound.format);
150   break;
151  default:
152/*
153   RSD_BUFSIZE,
154   RSD_LATENCY,
155*/
156     ROAR_DBG("rsd_set_param(rd=%p, option=%i, param=%p) = -1", rd, option, param);
157    return -1;
158   break;
159 }
160
161 ROAR_DBG("rsd_set_param(rd=%p, option=%i, param=%p) = 0", rd, option, param);
162 return 0;
163}
164
165static int libroarrsound_connect (struct libroarrsound * self) {
166 char * host;
167
168 if ( self->flags & LIBROARRSOUND_FLAGS_CONNECTED )
169  return 0;
170
171 host = self->rsound.host;
172
173 if ( host == NULL )
174  host = getenv("RSD_SERVER");
175
176 // FIXME: we currently ignore the port. :(
177
178 ROAR_DBG("libroarrsound_connect(self=%p): try to connect to: %s", self, host);
179
180 if ( roar_simple_connect(&(self->con), host, self->rsound.identity) == -1 ) {
181  ROAR_DBG("libroarrsound_connect(self=%p) = -1 // can not connect to server", self);
182  return -1;
183 }
184
185 self->flags |= LIBROARRSOUND_FLAGS_CONNECTED;
186
187 ROAR_DBG("libroarrsound_connect(self=%p) = 0", self);
188 return 0;
189}
190
191/* Establishes connection to server. Might fail if connection can't be established or that one of
192   the mandatory options isn't set in rsd_set_param(). This needs to be called after params have been set
193   with rsd_set_param(), and before rsd_write(). */
194int rsd_start (rsound_t *rd) {
195 struct libroarrsound * self = (struct libroarrsound *)rd;
196 int bits  = 16;
197 int codec;
198
199 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
200
201 if ( self == NULL )
202  return -1;
203
204 if ( self->flags & LIBROARRSOUND_FLAGS_STREAMING )
205  return 0;
206
207 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
208
209 if ( !(self->flags & LIBROARRSOUND_FLAGS_CONNECTED) ) {
210  if ( libroarrsound_connect(self) == -1 )
211   return -1;
212 }
213
214 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
215
216 switch (self->rsound.format) {
217  case RSD_S16_LE:
218    codec = ROAR_CODEC_PCM_S_LE;
219   break;
220  case RSD_S16_BE:
221    codec = ROAR_CODEC_PCM_S_BE;
222   break;
223  case RSD_S16_NE:
224    codec = ROAR_CODEC_PCM_S;
225   break;
226  case RSD_U16_LE:
227    codec = ROAR_CODEC_PCM_U_LE;
228   break;
229  case RSD_U16_BE:
230    codec = ROAR_CODEC_PCM_U_BE;
231   break;
232  case RSD_U16_NE:
233    codec = ROAR_CODEC_PCM_U;
234   break;
235  case RSD_S8:
236    codec = ROAR_CODEC_PCM_S;
237    bits  = 8;
238   break;
239  case RSD_U8:
240    codec = ROAR_CODEC_PCM_U;
241    bits  = 8;
242   break;
243  case RSD_ALAW:
244    codec = ROAR_CODEC_ALAW;
245    bits  = 8;
246   break;
247  case RSD_MULAW:
248    codec = ROAR_CODEC_MULAW;
249    bits  = 8;
250   break;
251  default:
252    return -1;
253   break;
254 }
255
256 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
257
258 if ( roar_vio_simple_new_stream_obj(&(self->vio), &(self->con), &(self->stream),
259                                     self->rsound.rate, self->rsound.channels, bits, codec, ROAR_DIR_PLAY) == -1 )
260  return -1;
261
262 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
263
264 self->flags |= LIBROARRSOUND_FLAGS_STREAMING;
265
266 ROAR_DBG("rsd_start(rd=%p) = 0", rd);
267
268 return 0;
269}
270
271/* Shuts down the rsound data structures, but returns the file descriptor associated with the connection.
272   The control socket will be shut down. If this function returns a negative number, the exec failed,
273   but the data structures will not be teared down.
274   Should a valid file descriptor be returned, it will always be non-blocking.  <<-- FIXME? */
275int rsd_exec (rsound_t *rd) {
276 struct libroarrsound * self = (struct libroarrsound *)rd;
277 int fh;
278
279 ROAR_DBG("rsd_exec(rd=%p) = ?", rd);
280
281 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
282  if ( rsd_start(rd) == -1 )
283   return -1;
284
285 ROAR_DBG("rsd_exec(rd=%p) = ?", rd);
286
287 if ( roar_vio_ctl(&(self->vio), ROAR_VIO_CTL_GET_FH, &fh) == -1 )
288  return -1;
289
290 ROAR_DBG("rsd_exec(rd=%p) = ?", rd);
291
292 if ( fh == -1 )
293  return -1;
294
295 ROAR_DBG("rsd_exec(rd=%p) = ?", rd);
296
297 if ( roar_stream_exec(&(self->con), &(self->stream)) == -1 )
298  return -1;
299
300 ROAR_DBG("rsd_exec(rd=%p) = ?", rd);
301
302 // reset flags:
303 if ( self->flags & LIBROARRSOUND_FLAGS_CONNECTED )
304  self->flags -= LIBROARRSOUND_FLAGS_CONNECTED;
305
306 if ( self->flags & LIBROARRSOUND_FLAGS_STREAMING )
307  self->flags -= LIBROARRSOUND_FLAGS_STREAMING;
308
309 ROAR_DBG("rsd_exec(rd=%p) = ?", rd);
310
311 // we hope nothing goes wrong here:
312 rsd_free(rd);
313
314 ROAR_DBG("rsd_exec(rd=%p) = %i", rd, fh);
315
316 return fh;
317}
318
319/* Disconnects from server. All audio data still in network buffer and other buffers will be dropped.
320   To continue playing, you will need to rsd_start() again. */
321int rsd_stop (rsound_t *rd) {
322 struct libroarrsound * self = (struct libroarrsound *)rd;
323 int ret;
324
325 if ( self == NULL )
326  return -1;
327
328 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
329  return 0;
330
331 ret = roar_vio_close(&(self->vio));
332
333 self->flags -= LIBROARRSOUND_FLAGS_STREAMING;
334
335 return ret;
336}
337
338/* Writes from buf to the internal buffer. Might fail if no connection is established,
339   or there was an unexpected error. This function will block until all data has
340   been written to the buffer. This function will return the number of bytes written to the buffer,
341   or 0 should it fail (disconnection from server). You will have to restart the stream again should this occur. */
342size_t rsd_write (rsound_t *rd, const void * buf, size_t size) {
343 struct libroarrsound * self = (struct libroarrsound *)rd;
344 ssize_t ret;
345
346 if ( self == NULL )
347  return -1;
348
349 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
350  return 0;
351
352 ret = roar_vio_write(&(self->vio), (void*)buf, size);
353
354 if ( ret == -1 )
355  return 0;
356
357 return ret;
358}
359
360/* Gets the position of the buffer pointer.
361   Not really interesting for normal applications.
362   Might be useful for implementing rsound on top of other blocking APIs. */
363size_t rsd_pointer (rsound_t *rd);
364
365/* Aquires how much data can be written to the buffer without blocking */
366size_t rsd_get_avail (rsound_t *rd);
367
368/* Aquires the latency at the moment for the audio stream. It is measured in bytes. Useful for syncing video and audio. */
369size_t rsd_delay (rsound_t *rd) {
370 (void)rd;
371 return 0; // TODO: FIXME: write some code to read pos from server.
372}
373
374/* Utility for returning latency in milliseconds. */
375size_t rsd_delay_ms (rsound_t *rd) {
376 if ( rd == NULL )
377  return -1;
378
379 if ( rd->rate <= 0 || rd->channels <= 0 )
380  return -1;
381
382 return (rsd_delay(rd) * 1000) / (rd->rate * rd->channels * rd->framesize);
383}
384
385/* Returns bytes per sample */
386int rsd_samplesize( rsound_t *rd ) {
387 if ( rd == NULL )
388  return -1;
389
390 return rd->framesize;
391}
392
393/* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY
394   Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set
395   with RSD_LATENCY, this function will do nothing. */
396void rsd_delay_wait(rsound_t *rd);
397
398
399/* Pauses or unpauses a stream. pause -> enable = 1
400   This function essentially calls on start() and stop(). This behavior might be changed later. */
401int rsd_pause (rsound_t *rd, int enable) {
402 struct libroarrsound * self = (struct libroarrsound *)rd;
403
404 if ( self == NULL )
405  return -1;
406
407 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
408  return -1;
409
410 return roar_stream_set_flags(&(self->con), &(self->stream), ROAR_FLAG_PAUSE, enable ? ROAR_SET_FLAG : ROAR_RESET_FLAG);
411}
412
413//ll
Note: See TracBrowser for help on using the repository browser.