source: roaraudio/libroarrsound/libroarrsound.c @ 3889:cab8aaa99718

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

added rsd_delay_ms() and rsd_samplesize() as required by newer versions librsound

File size: 9.2 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 return 0;
80}
81
82/* Frees an rsound_t struct. */
83int rsd_free (rsound_t *rd) {
84 struct libroarrsound * self = (struct libroarrsound *)rd;
85 int ret = 0;
86
87 if ( self == NULL )
88  return -1;
89
90 if ( self->flags & LIBROARRSOUND_FLAGS_CONNECTED )
91  if ( roar_disconnect(&(self->con)) == -1 )
92   ret = -1;
93
94 if ( self->flags & LIBROARRSOUND_FLAGS_STREAMING )
95  if ( roar_vio_close(&(self->vio)) == -1 )
96   ret = -1;
97
98 if ( self->rsound.host != NULL )
99  roar_mm_free(self->rsound.host);
100
101 if ( self->rsound.port != NULL )
102  roar_mm_free(self->rsound.port);
103
104 roar_mm_free(self);
105
106 return ret;
107}
108
109int rsd_set_param (rsound_t *rd, enum rsd_settings option, void* param) {
110 struct libroarrsound * self = (struct libroarrsound *)rd;
111
112 ROAR_DBG("rsd_set_param(rd=%p, option=%i, param=%p) = ?", rd, option, param);
113
114 if ( self == NULL || param == NULL )
115  return -1;
116
117 switch (option) {
118  // connection settings:
119  case RSD_HOST:
120    if ( self->rsound.host != NULL )
121     roar_mm_free(self->rsound.host);
122
123    self->rsound.host = roar_mm_strdup(param);
124   break;
125  case RSD_PORT:
126    if ( self->rsound.port != NULL )
127     roar_mm_free(self->rsound.port);
128
129    self->rsound.port = roar_mm_strdup(param);
130   break;
131  // stream settings:
132  case RSD_SAMPLERATE:
133    self->rsound.rate = *(int*)param;
134   break;
135  case RSD_CHANNELS:
136    self->rsound.channels = *(int*)param;
137   break;
138  case RSD_FORMAT:
139    self->rsound.format = *(int*)param;
140    self->rsound.framesize = libroarrsound_fmt2fs(self->rsound.format);
141   break;
142  default:
143/*
144   RSD_BUFSIZE,
145   RSD_LATENCY,
146*/
147     ROAR_DBG("rsd_set_param(rd=%p, option=%i, param=%p) = -1", rd, option, param);
148    return -1;
149   break;
150 }
151
152 ROAR_DBG("rsd_set_param(rd=%p, option=%i, param=%p) = 0", rd, option, param);
153 return 0;
154}
155
156static int libroarrsound_connect (struct libroarrsound * self) {
157 char * host;
158
159 if ( self->flags & LIBROARRSOUND_FLAGS_CONNECTED )
160  return 0;
161
162 host = self->rsound.host;
163
164 if ( host == NULL )
165  host = getenv("RSD_SERVER");
166
167 // FIXME: we currently ignore the port. :(
168
169 ROAR_DBG("libroarrsound_connect(self=%p): try to connect to: %s", self, host);
170
171 if ( roar_simple_connect(&(self->con), host, "libroarrsound client") == -1 ) {
172  ROAR_DBG("libroarrsound_connect(self=%p) = -1 // can not connect to server", self);
173  return -1;
174 }
175
176 self->flags |= LIBROARRSOUND_FLAGS_CONNECTED;
177
178 ROAR_DBG("libroarrsound_connect(self=%p) = 0", self);
179 return 0;
180}
181
182/* Establishes connection to server. Might fail if connection can't be established or that one of
183   the mandatory options isn't set in rsd_set_param(). This needs to be called after params have been set
184   with rsd_set_param(), and before rsd_write(). */
185int rsd_start (rsound_t *rd) {
186 struct libroarrsound * self = (struct libroarrsound *)rd;
187 int bits  = 16;
188 int codec;
189
190 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
191
192 if ( self == NULL )
193  return -1;
194
195 if ( self->flags & LIBROARRSOUND_FLAGS_STREAMING )
196  return 0;
197
198 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
199
200 if ( !(self->flags & LIBROARRSOUND_FLAGS_CONNECTED) ) {
201  if ( libroarrsound_connect(self) == -1 )
202   return -1;
203 }
204
205 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
206
207 switch (self->rsound.format) {
208  case RSD_S16_LE:
209    codec = ROAR_CODEC_PCM_S_LE;
210   break;
211  case RSD_S16_BE:
212    codec = ROAR_CODEC_PCM_S_BE;
213   break;
214  case RSD_S16_NE:
215    codec = ROAR_CODEC_PCM_S;
216   break;
217  case RSD_U16_LE:
218    codec = ROAR_CODEC_PCM_U_LE;
219   break;
220  case RSD_U16_BE:
221    codec = ROAR_CODEC_PCM_U_BE;
222   break;
223  case RSD_U16_NE:
224    codec = ROAR_CODEC_PCM_U;
225   break;
226  case RSD_S8:
227    codec = ROAR_CODEC_PCM_S;
228    bits  = 8;
229   break;
230  case RSD_U8:
231    codec = ROAR_CODEC_PCM_U;
232    bits  = 8;
233   break;
234  case RSD_ALAW:
235    codec = ROAR_CODEC_ALAW;
236    bits  = 8;
237   break;
238  case RSD_MULAW:
239    codec = ROAR_CODEC_MULAW;
240    bits  = 8;
241   break;
242  default:
243    return -1;
244   break;
245 }
246
247 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
248
249 if ( roar_vio_simple_new_stream_obj(&(self->vio), &(self->con), &(self->stream),
250                                     self->rsound.rate, self->rsound.channels, bits, codec, ROAR_DIR_PLAY) == -1 )
251  return -1;
252
253 ROAR_DBG("rsd_start(rd=%p) = ?", rd);
254
255 self->flags |= LIBROARRSOUND_FLAGS_STREAMING;
256
257 ROAR_DBG("rsd_start(rd=%p) = 0", rd);
258
259 return 0;
260}
261
262/* Disconnects from server. All audio data still in network buffer and other buffers will be dropped.
263   To continue playing, you will need to rsd_start() again. */
264int rsd_stop (rsound_t *rd) {
265 struct libroarrsound * self = (struct libroarrsound *)rd;
266 int ret;
267
268 if ( self == NULL )
269  return -1;
270
271 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
272  return 0;
273
274 ret = roar_vio_close(&(self->vio));
275
276 self->flags -= LIBROARRSOUND_FLAGS_STREAMING;
277
278 return ret;
279}
280
281/* Writes from buf to the internal buffer. Might fail if no connection is established,
282   or there was an unexpected error. This function will block until all data has
283   been written to the buffer. This function will return the number of bytes written to the buffer,
284   or 0 should it fail (disconnection from server). You will have to restart the stream again should this occur. */
285size_t rsd_write (rsound_t *rd, const void * buf, size_t size) {
286 struct libroarrsound * self = (struct libroarrsound *)rd;
287 ssize_t ret;
288
289 if ( self == NULL )
290  return -1;
291
292 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
293  return 0;
294
295 ret = roar_vio_write(&(self->vio), (void*)buf, size);
296
297 if ( ret == -1 )
298  return 0;
299
300 return ret;
301}
302
303/* Gets the position of the buffer pointer.
304   Not really interesting for normal applications.
305   Might be useful for implementing rsound on top of other blocking APIs. */
306size_t rsd_pointer (rsound_t *rd);
307
308/* Aquires how much data can be written to the buffer without blocking */
309size_t rsd_get_avail (rsound_t *rd);
310
311/* Aquires the latency at the moment for the audio stream. It is measured in bytes. Useful for syncing video and audio. */
312size_t rsd_delay (rsound_t *rd) {
313 (void)rd;
314 return 0; // TODO: FIXME: write some code to read pos from server.
315}
316
317/* Utility for returning latency in milliseconds. */
318size_t rsd_delay_ms (rsound_t *rd) {
319 if ( rd == NULL )
320  return -1;
321
322 if ( rd->rate <= 0 || rd->channels <= 0 )
323  return -1;
324
325 return (rsd_delay(rd) * 1000) / (rd->rate * rd->channels * rd->framesize);
326}
327
328/* Returns bytes per sample */
329int rsd_samplesize( rsound_t *rd ) {
330 if ( rd == NULL )
331  return -1;
332
333 return rd->framesize;
334}
335
336/* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY
337   Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set
338   with RSD_LATENCY, this function will do nothing. */
339void rsd_delay_wait(rsound_t *rd);
340
341
342/* Pauses or unpauses a stream. pause -> enable = 1
343   This function essentially calls on start() and stop(). This behavior might be changed later. */
344int rsd_pause (rsound_t *rd, int enable) {
345 struct libroarrsound * self = (struct libroarrsound *)rd;
346
347 if ( self == NULL )
348  return -1;
349
350 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
351  return -1;
352
353 return roar_stream_set_flags(&(self->con), &(self->stream), ROAR_FLAG_PAUSE, enable ? ROAR_SET_FLAG : ROAR_RESET_FLAG);
354}
355
356//ll
Note: See TracBrowser for help on using the repository browser.