source: roaraudio/libroar/stream.c @ 1137:700c32ffc876

Last change on this file since 1137:700c32ffc876 was 1137:700c32ffc876, checked in by phi, 15 years ago

insert a new parameter for the ss streucture: delay in mu-sec

File size: 10.6 KB
Line 
1//stream.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37int roar_stream_connect (struct roar_connection * con, struct roar_stream * s, int dir) {
38 struct roar_message m;
39
40 s->dir = dir;
41
42 m.cmd     = ROAR_CMD_NEW_STREAM;
43 m.stream  = -1;
44 m.pos     = 0;
45
46 roar_stream_s2m(s, &m);
47
48 if ( roar_req(con, &m, NULL) != 0 )
49  return -1;
50
51 if ( m.cmd == ROAR_CMD_OK ) {
52  s->id = m.stream;
53
54  ROAR_DBG("roar_stream_connect(*) = 0");
55  return 0;
56 }
57
58 ROAR_ERR("roar_stream_connect(*): Connecting new stream faild!");
59 ROAR_DBG("roar_stream_connect(*) = -1");
60 return -1;
61}
62
63int roar_stream_new (struct roar_stream * s, unsigned int rate,
64                     unsigned int channels, unsigned int bits, unsigned int codec) {
65
66
67 s->fh         = -1;
68 s->id         = -1;
69 s->pos        = 0;
70 s->pos_rel_id = -1;
71
72 s->dir        = ROAR_DIR_DEFAULT;
73
74 s->datalen    = 0;
75 s->offset     = 0;
76
77 s->database   = NULL;
78 s->dataoff    = NULL;
79
80 s->info.rate     = rate;
81 s->info.channels = channels;
82 s->info.bits     = bits;
83 s->info.codec    = codec;
84
85 if ( bits > ROAR_BITS_MAX )
86  return -1;
87
88 return 0;
89}
90
91int roar_stream_exec    (struct roar_connection * con, struct roar_stream * s) {
92 struct roar_message m;
93
94 m.cmd     = ROAR_CMD_EXEC_STREAM;
95 m.stream  = s->id;
96 m.datalen = 0;
97 m.pos     = 0;
98
99 if ( roar_req(con, &m, NULL) == -1 )
100  return -1;
101
102 if ( m.cmd == ROAR_CMD_OK )
103  return 0;
104 return -1;
105}
106
107int roar_stream_connect_to (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
108 struct roar_message m;
109
110 if ( roar_stream_connect_to_ask(con, s, type, host, port) == -1 )
111  return -1;
112
113 if ( roar_recv_message(con, &m, NULL) == -1 )
114  return -1;
115
116 if ( m.cmd == ROAR_CMD_OK )
117  return 0;
118 return -1;
119}
120
121int roar_stream_connect_to_ask (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
122 struct roar_message m;
123 int len = 0;
124
125 if ( host == NULL )
126  return -1;
127
128 ROAR_DBG("roar_stream_connect_to_ask(*): Ask the server to connect to: %s:%i", host, port);
129
130 m.cmd     = ROAR_CMD_CON_STREAM;
131 m.stream  = s->id;
132 m.pos     = 0;
133
134 m.data[0] = 0;
135 m.data[1] = type;
136 ((uint16_t*)&(m.data))[1] = ROAR_HOST2NET16(port);
137
138 len = strlen(host);
139
140 if ( len > 76 )
141  return -1;
142
143 strncpy(&(m.data[4]), host, len);
144
145 m.datalen = len + 4;
146
147 if ( roar_send_message(con, &m, NULL) == -1 )
148  return -1;
149
150 return 0;
151}
152
153int roar_stream_passfh  (struct roar_connection * con, struct roar_stream * s, int fh) {
154 struct roar_message m;
155
156 m.cmd     = ROAR_CMD_PASSFH;
157 m.stream  = s->id;
158 m.pos     = 0;
159 m.datalen = 0;
160
161 ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = ?", con->fh, s->id, fh);
162
163 if ( roar_send_message(con, &m, NULL) == -1 ) {
164  ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = -1 // can not send message", con->fh, s->id, fh);
165  return -1;
166 }
167
168 ROAR_DBG("roar_stream_passfh(*): msg send");
169
170 if ( roar_socket_send_fh(con->fh, fh, NULL, 0) == -1 )
171  return -1;
172
173 ROAR_DBG("roar_stream_passfh(*): fh send");
174
175 if ( roar_recv_message(con, &m, NULL) == -1 )
176  return -1;
177
178 ROAR_DBG("roar_stream_passfh(*): mes recved");
179
180 if ( m.cmd == ROAR_CMD_OK )
181  return 0;
182
183 return -1;
184}
185
186int roar_stream_attach_simple (struct roar_connection * con, struct roar_stream * s, int client) {
187 struct roar_message m;
188 uint16_t * info = (uint16_t *) m.data;
189 int i;
190
191 m.cmd     = ROAR_CMD_ATTACH;
192 m.stream  = s->id;
193 m.pos     = 0;
194 m.datalen = 6;
195
196 info[0] = 0;
197 info[1] = ROAR_ATTACH_SIMPLE;
198 info[2] = client;
199
200 for (i = 0; i < m.datalen/2; i++) {
201  info[i] = ROAR_HOST2NET16(info[i]);
202 }
203
204 if ( roar_req(con, &m, NULL) == -1 )
205  return -1;
206
207 if ( m.cmd != ROAR_CMD_OK )
208  return -1;
209
210 return 0;
211}
212
213int roar_stream_add_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
214 struct roar_message m;
215
216 m.cmd     = ROAR_CMD_ADD_DATA;
217 m.stream  = s->id;
218 m.pos     = 0;
219 m.datalen = len;
220
221// if ( roar_req(con, &m, (void**)&data) == -1 )
222//  return -1;
223 if ( roar_send_message(con, &m, data) != 0 )
224  return -1;
225
226 if ( roar_recv_message(con, &m, NULL) == -1 )
227  return -1;
228
229 if ( m.cmd == ROAR_CMD_OK )
230  return 0;
231 return -1;
232}
233
234int roar_stream_send_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
235 if ( ! s )
236  return -1;
237
238 if ( s->fh == -1 ) {
239  if ( !con )
240   return -1;
241
242  if ( roar_stream_add_data(con, s, data, len) == -1 )
243   return -1;
244
245  return len;
246 }
247
248 return write(s->fh, data, len);
249}
250
251int roar_stream_get_info (struct roar_connection * con, struct roar_stream * s, struct roar_stream_info * info) {
252 struct roar_message m;
253 uint16_t * data = (uint16_t *) m.data;
254 int i;
255
256 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
257 m.stream  = s->id;
258 m.datalen = 4;
259 m.pos     = 0;
260
261 data[0] = 0; // Version and reserved
262 data[1] = 1; // stream
263
264 for (i = 0; i < m.datalen/2; i++) {
265  data[i] = ROAR_HOST2NET16(data[i]);
266 }
267
268 if ( roar_req(con, &m, NULL) == -1 )
269  return -1;
270
271 if ( m.cmd != ROAR_CMD_OK )
272  return -1;
273
274 for (i = 0; i < m.datalen/2; i++) {
275  data[i] = ROAR_NET2HOST16(data[i]);
276 }
277
278 if ( m.datalen < 7*2 )
279  return -1;
280
281 if ( data[0] != 0 || data[1] != 1 )
282  return -1;
283
284 memset(info, 0, sizeof(struct roar_stream_info));
285
286 info->block_size     = data[2];
287 info->pre_underruns  = data[3];
288 info->post_underruns = data[4];
289 info->codec          = data[5];
290 info->flags          = data[6];
291 info->delay          = data[7]*1000;
292
293 return 0;
294}
295
296int roar_stream_set_flags (struct roar_connection * con, struct roar_stream * s, int flags, int reset) {
297 struct roar_message m;
298 uint16_t * data = (uint16_t *) m.data;
299 int i;
300
301 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
302 m.stream  = s->id;
303 m.datalen = 8;
304 m.pos     = 0;
305
306 data[0] = 0; // Version and reserved
307 data[1] = 2; // flags
308 data[2] = reset == ROAR_RESET_FLAG ? ROAR_RESET_FLAG : ROAR_SET_FLAG;
309 data[3] = flags;
310
311 for (i = 0; i < m.datalen/2; i++) {
312  data[i] = ROAR_HOST2NET16(data[i]);
313 }
314
315 if ( roar_req(con, &m, NULL) == -1 )
316  return -1;
317
318 if ( m.cmd != ROAR_CMD_OK )
319  return -1;
320
321 return 0;
322}
323
324#define _ROAR_STREAM_MESSAGE_LEN ((5+1)*4)
325
326int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m) {
327 uint32_t * data;
328 int i;
329
330 if ( !(s && m) )
331  return -1;
332
333 m->datalen = _ROAR_STREAM_MESSAGE_LEN;
334 data = (uint32_t*) m->data;
335
336 data[0] = s->dir;
337 data[1] = s->pos_rel_id;
338 data[2] = s->info.rate;
339 data[3] = s->info.bits;
340 data[4] = s->info.channels;
341 data[5] = s->info.codec;
342
343 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
344  data[i] = ROAR_HOST2NET32(data[i]);
345
346 ROAR_DBG("roar_stream_s2m(*): s->info:");
347 roar_debug_audio_info_print(&s->info);
348
349 m->pos = s->pos;
350
351 return 0;
352}
353int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m) {
354 uint32_t * data;
355 int i;
356
357 if ( !(s && m) )
358  return -1;
359
360 if ( m->datalen != _ROAR_STREAM_MESSAGE_LEN )
361  return -1;
362
363 s->pos = m->pos;
364
365 data = (uint32_t*) m->data;
366
367 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
368  data[i] = ROAR_NET2HOST32(data[i]);
369
370 s->id            = m->stream;
371 s->dir           = data[0];
372 s->pos_rel_id    = data[1];
373 s->info.rate     = data[2];
374 s->info.bits     = data[3];
375 s->info.channels = data[4];
376 s->info.codec    = data[5];
377
378 ROAR_DBG("roar_stream_m2s(*): s->info:");
379 roar_debug_audio_info_print(&s->info);
380
381 return 0;
382}
383
384
385// codec funcs:
386
387/*
388#define roar_codec2str(x) ((x) == ROAR_CODEC_PCM_S_LE  ? "pcm_s_le"  : (x) == ROAR_CODEC_PCM_S_BE  ? "pcm_s_be"  : \
389                           (x) == ROAR_CODEC_PCM_S_PDP ? "pcm_s_pdp" : (x) == ROAR_CODEC_MIDI_FILE ? "midi_file" : \
390                           "unknown" )
391*/
392
393struct {
394 int    codec;
395 char * name;
396} _libroar_codec[] = {
397 // PCM:
398 {ROAR_CODEC_PCM_S_LE,    "pcm_s_le"   },
399 {ROAR_CODEC_PCM_S_BE,    "pcm_s_be"   },
400 {ROAR_CODEC_PCM_S_PDP,   "pcm_s_pdp"  },
401 {ROAR_CODEC_PCM_U_LE,    "pcm_u_le"   },
402 {ROAR_CODEC_PCM_U_BE,    "pcm_u_be"   },
403 {ROAR_CODEC_PCM_U_PDP,   "pcm_u_pdp"  },
404 {ROAR_CODEC_DEFAULT,     "default"    }, // alias
405 {ROAR_CODEC_DEFAULT,     "pcm"        }, // alias
406 {ROAR_CODEC_DEFAULT,     "raw"        }, // alias
407
408 // MIDI:
409 {ROAR_CODEC_MIDI_FILE,   "midi_file"  },
410
411 // XIPH:
412 {ROAR_CODEC_OGG_VORBIS,  "ogg_vorbis" },
413 {ROAR_CODEC_OGG_VORBIS,  "vorbis"     }, // alias
414 {ROAR_CODEC_FLAC,        "flac"       },
415 {ROAR_CODEC_OGG_SPEEX,   "ogg_speex"  },
416 {ROAR_CODEC_OGG_SPEEX,   "speex"      }, // alias
417 {ROAR_CODEC_OGG_FLAC,    "ogg_flac"   },
418 {ROAR_CODEC_OGG_GENERAL, "ogg_general"},
419 {ROAR_CODEC_ROAR_CELT,   "roar_celt"  },
420 {ROAR_CODEC_ROAR_SPEEX,  "roar_speex" },
421
422 // RAUM:
423 {ROAR_CODEC_RAUM,        "raum"       },
424 {ROAR_CODEC_RAUM_VORBIS, "raum_vorbis"},
425
426 // RIFF/WAVE like:
427 {ROAR_CODEC_RIFF_WAVE,   "riff_wave"  },
428 {ROAR_CODEC_RIFF_WAVE,   "wave"       }, // alias
429 {ROAR_CODEC_RIFF_WAVE,   "wav"        }, // alias
430
431 //Log codecs:
432 {ROAR_CODEC_ALAW,        "alaw"       },
433 {ROAR_CODEC_MULAW,       "mulaw"      },
434 {ROAR_CODEC_MULAW,       "ulaw"       }, // alias
435
436 {-1, NULL}
437};
438
439int roar_str2codec(char * codec) {
440 int i;
441 int guess;
442
443 if ( codec == NULL || *codec == 0 )
444  return ROAR_CODEC_DEFAULT;
445
446 if ( (guess = atoi(codec)) > 0 )
447  return guess;
448
449 if ( codec == NULL || *codec == 0 )
450  return ROAR_CODEC_DEFAULT;
451
452 for (i = 0; _libroar_codec[i].codec != -1; i++)
453  if ( strcasecmp(_libroar_codec[i].name, codec) == 0 )
454   return _libroar_codec[i].codec;
455
456 return -1;
457}
458
459
460char * roar_codec2str (int codec) {
461 int i;
462
463 for (i = 0; _libroar_codec[i].codec != -1; i++)
464  if ( _libroar_codec[i].codec == codec )
465   return _libroar_codec[i].name;
466
467 return "unknown";
468}
469
470//ll
Note: See TracBrowser for help on using the repository browser.