source: roaraudio/libroarrsound/libroarrsound.c @ 3916:b9dead066419

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

ported RSD_IDENTITY support

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