source: roaraudio/libroar/stream.c @ 1804:fcbd866258e7

Last change on this file since 1804:fcbd866258e7 was 1804:fcbd866258e7, checked in by phi, 15 years ago

removed unused struct fiealds

File size: 11.8 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/*
75 s->datalen    = 0;
76 s->offset     = 0;
77
78 s->database   = NULL;
79 s->dataoff    = NULL;
80*/
81
82 s->info.rate     = rate;
83 s->info.channels = channels;
84 s->info.bits     = bits;
85 s->info.codec    = codec;
86
87 if ( bits > ROAR_BITS_MAX )
88  return -1;
89
90 return 0;
91}
92
93int roar_stream_new_by_id(struct roar_stream * s, int id) {
94 if ( s == NULL )
95  return -1;
96
97 if ( roar_stream_new_empty(s) == -1 )
98  return -1;
99
100 return roar_stream_set_id(s, id);
101}
102
103int roar_stream_new_empty(struct roar_stream * s) {
104 if ( s == NULL )
105  return -1;
106
107 return roar_stream_new(s, 0, 0, 0, 0);
108}
109
110int roar_stream_set_id (struct roar_stream * s, int id) {
111 if ( s == NULL )
112  return -1;
113
114 s->id = id;
115
116 return 0;
117}
118
119int roar_stream_get_id (struct roar_stream * s) {
120 if ( s == NULL )
121  return -1;
122
123 return s->id;
124}
125
126int roar_stream_set_fh (struct roar_stream * s, int fh) {
127 if ( s == NULL )
128  return -1;
129
130 s->fh = fh;
131
132 return 0;
133}
134
135int roar_stream_get_fh (struct roar_stream * s) {
136 if ( s == NULL )
137  return -1;
138
139 return s->fh;
140}
141
142
143int roar_stream_exec    (struct roar_connection * con, struct roar_stream * s) {
144 struct roar_message m;
145
146 m.cmd     = ROAR_CMD_EXEC_STREAM;
147 m.stream  = s->id;
148 m.datalen = 0;
149 m.pos     = 0;
150
151 if ( roar_req(con, &m, NULL) == -1 )
152  return -1;
153
154 if ( m.cmd == ROAR_CMD_OK )
155  return 0;
156 return -1;
157}
158
159int roar_stream_connect_to (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
160 struct roar_message m;
161
162 if ( roar_stream_connect_to_ask(con, s, type, host, port) == -1 )
163  return -1;
164
165 if ( roar_recv_message(con, &m, NULL) == -1 )
166  return -1;
167
168 if ( m.cmd == ROAR_CMD_OK )
169  return 0;
170 return -1;
171}
172
173int roar_stream_connect_to_ask (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
174 struct roar_message m;
175 int len = 0;
176
177 if ( host == NULL )
178  return -1;
179
180 ROAR_DBG("roar_stream_connect_to_ask(*): Ask the server to connect to: %s:%i", host, port);
181
182 m.cmd     = ROAR_CMD_CON_STREAM;
183 m.stream  = s->id;
184 m.pos     = 0;
185
186 m.data[0] = 0;
187 m.data[1] = type;
188 ((uint16_t*)&(m.data))[1] = ROAR_HOST2NET16(port);
189
190 len = strlen(host);
191
192 if ( len > 76 )
193  return -1;
194
195 strncpy(&(m.data[4]), host, len);
196
197 m.datalen = len + 4;
198
199 if ( roar_send_message(con, &m, NULL) == -1 )
200  return -1;
201
202 return 0;
203}
204
205int roar_stream_passfh  (struct roar_connection * con, struct roar_stream * s, int fh) {
206 struct roar_message m;
207 int confh;
208
209 m.cmd     = ROAR_CMD_PASSFH;
210 m.stream  = s->id;
211 m.pos     = 0;
212 m.datalen = 0;
213
214 ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = ?", con->fh, s->id, fh);
215
216 if ( (confh = roar_get_connection_fh(con)) == -1 )
217  return -1;
218
219 if ( roar_send_message(con, &m, NULL) == -1 ) {
220  ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = -1 // can not send message", con->fh, s->id, fh);
221  return -1;
222 }
223
224 ROAR_DBG("roar_stream_passfh(*): msg send");
225
226 if ( roar_socket_send_fh(confh, fh, NULL, 0) == -1 )
227  return -1;
228
229 ROAR_DBG("roar_stream_passfh(*): fh send");
230
231 if ( roar_recv_message(con, &m, NULL) == -1 )
232  return -1;
233
234 ROAR_DBG("roar_stream_passfh(*): mes recved");
235
236 if ( m.cmd == ROAR_CMD_OK )
237  return 0;
238
239 return -1;
240}
241
242int roar_stream_attach_simple (struct roar_connection * con, struct roar_stream * s, int client) {
243 struct roar_message m;
244 uint16_t * info = (uint16_t *) m.data;
245 int i;
246
247 m.cmd     = ROAR_CMD_ATTACH;
248 m.stream  = s->id;
249 m.pos     = 0;
250 m.datalen = 6;
251
252 info[0] = 0;
253 info[1] = ROAR_ATTACH_SIMPLE;
254 info[2] = client;
255
256 for (i = 0; i < m.datalen/2; i++) {
257  info[i] = ROAR_HOST2NET16(info[i]);
258 }
259
260 if ( roar_req(con, &m, NULL) == -1 )
261  return -1;
262
263 if ( m.cmd != ROAR_CMD_OK )
264  return -1;
265
266 return 0;
267}
268
269int roar_stream_add_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
270 struct roar_message m;
271
272 m.cmd     = ROAR_CMD_ADD_DATA;
273 m.stream  = s->id;
274 m.pos     = 0;
275 m.datalen = len;
276
277// if ( roar_req(con, &m, (void**)&data) == -1 )
278//  return -1;
279 if ( roar_send_message(con, &m, data) != 0 )
280  return -1;
281
282 if ( roar_recv_message(con, &m, NULL) == -1 )
283  return -1;
284
285 if ( m.cmd == ROAR_CMD_OK )
286  return 0;
287 return -1;
288}
289
290int roar_stream_send_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
291 if ( ! s )
292  return -1;
293
294 if ( s->fh == -1 ) {
295  if ( !con )
296   return -1;
297
298  if ( roar_stream_add_data(con, s, data, len) == -1 )
299   return -1;
300
301  return len;
302 }
303
304#ifdef ROAR_HAVE_IO_POSIX
305 return write(s->fh, data, len);
306#endif
307
308 return -1;
309}
310
311int roar_stream_get_info (struct roar_connection * con, struct roar_stream * s, struct roar_stream_info * info) {
312 struct roar_message m;
313 uint16_t * data = (uint16_t *) m.data;
314 int i;
315
316 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
317 m.stream  = s->id;
318 m.datalen = 4;
319 m.pos     = 0;
320
321 data[0] = 0; // Version and reserved
322 data[1] = 1; // stream
323
324 for (i = 0; i < m.datalen/2; i++) {
325  data[i] = ROAR_HOST2NET16(data[i]);
326 }
327
328 if ( roar_req(con, &m, NULL) == -1 )
329  return -1;
330
331 if ( m.cmd != ROAR_CMD_OK )
332  return -1;
333
334 for (i = 0; i < m.datalen/2; i++) {
335  data[i] = ROAR_NET2HOST16(data[i]);
336 }
337
338 if ( m.datalen < 7*2 )
339  return -1;
340
341 if ( data[0] != 0 || data[1] != 1 )
342  return -1;
343
344 memset(info, 0, sizeof(struct roar_stream_info));
345
346 info->block_size     = data[2];
347 info->pre_underruns  = data[3];
348 info->post_underruns = data[4];
349 info->codec          = data[5];
350 info->flags          = data[6];
351 info->delay          = data[7]*1000;
352
353 return 0;
354}
355
356int roar_stream_set_flags (struct roar_connection * con, struct roar_stream * s, int flags, int reset) {
357 struct roar_message m;
358 uint16_t * data = (uint16_t *) m.data;
359 int i;
360
361 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
362 m.stream  = s->id;
363 m.datalen = 8;
364 m.pos     = 0;
365
366 data[0] = 0; // Version and reserved
367 data[1] = 2; // flags
368 data[2] = reset == ROAR_RESET_FLAG ? ROAR_RESET_FLAG : ROAR_SET_FLAG;
369 data[3] = flags;
370
371 for (i = 0; i < m.datalen/2; i++) {
372  data[i] = ROAR_HOST2NET16(data[i]);
373 }
374
375 if ( roar_req(con, &m, NULL) == -1 )
376  return -1;
377
378 if ( m.cmd != ROAR_CMD_OK )
379  return -1;
380
381 return 0;
382}
383
384#define _ROAR_STREAM_MESSAGE_LEN ((5+1)*4)
385
386int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m) {
387 uint32_t * data;
388 int i;
389
390 if ( !(s && m) )
391  return -1;
392
393 m->datalen = _ROAR_STREAM_MESSAGE_LEN;
394 data = (uint32_t*) m->data;
395
396 data[0] = s->dir;
397 data[1] = s->pos_rel_id;
398 data[2] = s->info.rate;
399 data[3] = s->info.bits;
400 data[4] = s->info.channels;
401 data[5] = s->info.codec;
402
403 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
404  data[i] = ROAR_HOST2NET32(data[i]);
405
406 ROAR_DBG("roar_stream_s2m(*): s->info:");
407 roar_debug_audio_info_print(&s->info);
408
409 m->pos = s->pos;
410
411 return 0;
412}
413int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m) {
414 uint32_t * data;
415 int i;
416
417 if ( !(s && m) )
418  return -1;
419
420 if ( m->datalen != _ROAR_STREAM_MESSAGE_LEN )
421  return -1;
422
423 s->pos = m->pos;
424
425 data = (uint32_t*) m->data;
426
427 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
428  data[i] = ROAR_NET2HOST32(data[i]);
429
430 s->id            = m->stream;
431 s->dir           = data[0];
432 s->pos_rel_id    = data[1];
433 s->info.rate     = data[2];
434 s->info.bits     = data[3];
435 s->info.channels = data[4];
436 s->info.codec    = data[5];
437
438 ROAR_DBG("roar_stream_m2s(*): s->info:");
439 roar_debug_audio_info_print(&s->info);
440
441 return 0;
442}
443
444
445// codec funcs:
446
447/*
448#define roar_codec2str(x) ((x) == ROAR_CODEC_PCM_S_LE  ? "pcm_s_le"  : (x) == ROAR_CODEC_PCM_S_BE  ? "pcm_s_be"  : \
449                           (x) == ROAR_CODEC_PCM_S_PDP ? "pcm_s_pdp" : (x) == ROAR_CODEC_MIDI_FILE ? "midi_file" : \
450                           "unknown" )
451*/
452
453struct {
454 int    codec;
455 char * name;
456} _libroar_codec[] = {
457 // PCM:
458 {ROAR_CODEC_PCM_S_LE,    "pcm_s_le"   },
459 {ROAR_CODEC_PCM_S_BE,    "pcm_s_be"   },
460 {ROAR_CODEC_PCM_S_PDP,   "pcm_s_pdp"  },
461 {ROAR_CODEC_PCM_U_LE,    "pcm_u_le"   },
462 {ROAR_CODEC_PCM_U_BE,    "pcm_u_be"   },
463 {ROAR_CODEC_PCM_U_PDP,   "pcm_u_pdp"  },
464 {ROAR_CODEC_DEFAULT,     "default"    }, // alias
465 {ROAR_CODEC_DEFAULT,     "pcm"        }, // alias
466 {ROAR_CODEC_DEFAULT,     "raw"        }, // alias
467
468 // MIDI:
469 {ROAR_CODEC_MIDI_FILE,   "midi_file"  },
470
471 // XIPH:
472 {ROAR_CODEC_OGG_VORBIS,  "ogg_vorbis" },
473 {ROAR_CODEC_OGG_VORBIS,  "vorbis"     }, // alias
474 {ROAR_CODEC_FLAC,        "flac"       },
475 {ROAR_CODEC_OGG_SPEEX,   "ogg_speex"  },
476 {ROAR_CODEC_OGG_SPEEX,   "speex"      }, // alias
477 {ROAR_CODEC_OGG_FLAC,    "ogg_flac"   },
478 {ROAR_CODEC_OGG_GENERAL, "ogg_general"},
479 {ROAR_CODEC_ROAR_CELT,   "roar_celt"  },
480 {ROAR_CODEC_ROAR_SPEEX,  "roar_speex" },
481
482 // RAUM:
483 {ROAR_CODEC_RAUM,        "raum"       },
484 {ROAR_CODEC_RAUM_VORBIS, "raum_vorbis"},
485
486 // RIFF/WAVE like:
487 {ROAR_CODEC_RIFF_WAVE,   "riff_wave"  },
488 {ROAR_CODEC_RIFF_WAVE,   "wave"       }, // alias
489 {ROAR_CODEC_RIFF_WAVE,   "wav"        }, // alias
490
491 //Log codecs:
492 {ROAR_CODEC_ALAW,        "alaw"       },
493 {ROAR_CODEC_MULAW,       "mulaw"      },
494 {ROAR_CODEC_MULAW,       "ulaw"       }, // alias
495
496 // Meta Codecs:
497 {ROAR_CODEC_META_VCLT,     "meta_vclt"    },
498 {ROAR_CODEC_META_RALT,     "meta_ralt"    },
499 {ROAR_CODEC_META_RALB,     "meta_ralb"    },
500 {ROAR_CODEC_META_RALB_LE,  "meta_ralb_le" },
501 {ROAR_CODEC_META_RALB_BE,  "meta_ralb_be" },
502 {ROAR_CODEC_META_RALB_PDP, "meta_ralb_pdp"},
503
504 {-1, NULL}
505};
506
507int roar_str2codec(char * codec) {
508 int i;
509 int guess;
510
511 if ( codec == NULL || *codec == 0 )
512  return ROAR_CODEC_DEFAULT;
513
514 if ( (guess = atoi(codec)) > 0 )
515  return guess;
516
517 if ( codec == NULL || *codec == 0 )
518  return ROAR_CODEC_DEFAULT;
519
520 for (i = 0; _libroar_codec[i].codec != -1; i++)
521  if ( strcasecmp(_libroar_codec[i].name, codec) == 0 )
522   return _libroar_codec[i].codec;
523
524 return -1;
525}
526
527
528char * roar_codec2str (int codec) {
529 int i;
530
531 for (i = 0; _libroar_codec[i].codec != -1; i++)
532  if ( _libroar_codec[i].codec == codec )
533   return _libroar_codec[i].name;
534
535 return "unknown";
536}
537
538//ll
Note: See TracBrowser for help on using the repository browser.