source: roaraudio/libroarrsound/libroarrsound.c @ 3923:793cb71fdc16

Last change on this file since 3923:793cb71fdc16 was 3923:793cb71fdc16, checked in by phi, 14 years ago

free unused memory

File size: 10.5 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 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
280  if ( rsd_start(rd) == -1 )
281   return -1;
282
283 if ( roar_vio_ctl(&(self->vio), ROAR_VIO_CTL_GET_FH, &fh) == -1 )
284  return -1;
285
286 if ( fh == -1 )
287  return -1;
288
289 if ( roar_stream_exec(&(self->con), &(self->stream)) == -1 )
290  return -1;
291
292 // reset flags:
293 if ( self->flags & LIBROARRSOUND_FLAGS_CONNECTED )
294  self->flags -= LIBROARRSOUND_FLAGS_CONNECTED;
295
296 if ( self->flags & LIBROARRSOUND_FLAGS_STREAMING )
297  self->flags -= LIBROARRSOUND_FLAGS_STREAMING;
298
299 // we hope nothing goes wrong here:
300 rsd_free(rd);
301
302 return fh;
303}
304
305/* Disconnects from server. All audio data still in network buffer and other buffers will be dropped.
306   To continue playing, you will need to rsd_start() again. */
307int rsd_stop (rsound_t *rd) {
308 struct libroarrsound * self = (struct libroarrsound *)rd;
309 int ret;
310
311 if ( self == NULL )
312  return -1;
313
314 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
315  return 0;
316
317 ret = roar_vio_close(&(self->vio));
318
319 self->flags -= LIBROARRSOUND_FLAGS_STREAMING;
320
321 return ret;
322}
323
324/* Writes from buf to the internal buffer. Might fail if no connection is established,
325   or there was an unexpected error. This function will block until all data has
326   been written to the buffer. This function will return the number of bytes written to the buffer,
327   or 0 should it fail (disconnection from server). You will have to restart the stream again should this occur. */
328size_t rsd_write (rsound_t *rd, const void * buf, size_t size) {
329 struct libroarrsound * self = (struct libroarrsound *)rd;
330 ssize_t ret;
331
332 if ( self == NULL )
333  return -1;
334
335 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
336  return 0;
337
338 ret = roar_vio_write(&(self->vio), (void*)buf, size);
339
340 if ( ret == -1 )
341  return 0;
342
343 return ret;
344}
345
346/* Gets the position of the buffer pointer.
347   Not really interesting for normal applications.
348   Might be useful for implementing rsound on top of other blocking APIs. */
349size_t rsd_pointer (rsound_t *rd);
350
351/* Aquires how much data can be written to the buffer without blocking */
352size_t rsd_get_avail (rsound_t *rd);
353
354/* Aquires the latency at the moment for the audio stream. It is measured in bytes. Useful for syncing video and audio. */
355size_t rsd_delay (rsound_t *rd) {
356 (void)rd;
357 return 0; // TODO: FIXME: write some code to read pos from server.
358}
359
360/* Utility for returning latency in milliseconds. */
361size_t rsd_delay_ms (rsound_t *rd) {
362 if ( rd == NULL )
363  return -1;
364
365 if ( rd->rate <= 0 || rd->channels <= 0 )
366  return -1;
367
368 return (rsd_delay(rd) * 1000) / (rd->rate * rd->channels * rd->framesize);
369}
370
371/* Returns bytes per sample */
372int rsd_samplesize( rsound_t *rd ) {
373 if ( rd == NULL )
374  return -1;
375
376 return rd->framesize;
377}
378
379/* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY
380   Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set
381   with RSD_LATENCY, this function will do nothing. */
382void rsd_delay_wait(rsound_t *rd);
383
384
385/* Pauses or unpauses a stream. pause -> enable = 1
386   This function essentially calls on start() and stop(). This behavior might be changed later. */
387int rsd_pause (rsound_t *rd, int enable) {
388 struct libroarrsound * self = (struct libroarrsound *)rd;
389
390 if ( self == NULL )
391  return -1;
392
393 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
394  return -1;
395
396 return roar_stream_set_flags(&(self->con), &(self->stream), ROAR_FLAG_PAUSE, enable ? ROAR_SET_FLAG : ROAR_RESET_FLAG);
397}
398
399//ll
Note: See TracBrowser for help on using the repository browser.