source: roaraudio/libroarrsound/libroarrsound.c @ 3919:f5f82690acbd

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

test for RSD_IDENTITY

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