source: roaraudio/libroar/stream.c @ 1660:99bfd21f00ef

Last change on this file since 1660:99bfd21f00ef was 1660:99bfd21f00ef, checked in by phi, 15 years ago

changed name of fh in con struct to fh, this should all apps requiring the private member to fail to build, added function to get fh, change code to use them both everythere

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