source: roaraudio/libroarrsound/libroarrsound.c @ 3793:f2f6e3243599

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

added some debug lions

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