source: roaraudio/libroarrsound/libroarrsound.c @ 3865:d004ebed0dd4

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

use support more codecs and corrected prototyoe

File size: 8.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 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/* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY
318   Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set
319   with RSD_LATENCY, this function will do nothing. */
320void rsd_delay_wait(rsound_t *rd);
321
322
323/* Pauses or unpauses a stream. pause -> enable = 1
324   This function essentially calls on start() and stop(). This behavior might be changed later. */
325int rsd_pause (rsound_t *rd, int enable) {
326 struct libroarrsound * self = (struct libroarrsound *)rd;
327
328 if ( self == NULL )
329  return -1;
330
331 if ( !(self->flags & LIBROARRSOUND_FLAGS_STREAMING) )
332  return -1;
333
334 return roar_stream_set_flags(&(self->con), &(self->stream), ROAR_FLAG_PAUSE, enable ? ROAR_SET_FLAG : ROAR_RESET_FLAG);
335}
336
337//ll
Note: See TracBrowser for help on using the repository browser.