source: roaraudio/libroar/stream.c @ 1211:cd16786b451f

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

added codec IDs for meta data streams

File size: 11.7 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
206 m.cmd     = ROAR_CMD_PASSFH;
207 m.stream  = s->id;
208 m.pos     = 0;
209 m.datalen = 0;
210
211 ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = ?", con->fh, s->id, fh);
212
213 if ( roar_send_message(con, &m, NULL) == -1 ) {
214  ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = -1 // can not send message", con->fh, s->id, fh);
215  return -1;
216 }
217
218 ROAR_DBG("roar_stream_passfh(*): msg send");
219
220 if ( roar_socket_send_fh(con->fh, fh, NULL, 0) == -1 )
221  return -1;
222
223 ROAR_DBG("roar_stream_passfh(*): fh send");
224
225 if ( roar_recv_message(con, &m, NULL) == -1 )
226  return -1;
227
228 ROAR_DBG("roar_stream_passfh(*): mes recved");
229
230 if ( m.cmd == ROAR_CMD_OK )
231  return 0;
232
233 return -1;
234}
235
236int roar_stream_attach_simple (struct roar_connection * con, struct roar_stream * s, int client) {
237 struct roar_message m;
238 uint16_t * info = (uint16_t *) m.data;
239 int i;
240
241 m.cmd     = ROAR_CMD_ATTACH;
242 m.stream  = s->id;
243 m.pos     = 0;
244 m.datalen = 6;
245
246 info[0] = 0;
247 info[1] = ROAR_ATTACH_SIMPLE;
248 info[2] = client;
249
250 for (i = 0; i < m.datalen/2; i++) {
251  info[i] = ROAR_HOST2NET16(info[i]);
252 }
253
254 if ( roar_req(con, &m, NULL) == -1 )
255  return -1;
256
257 if ( m.cmd != ROAR_CMD_OK )
258  return -1;
259
260 return 0;
261}
262
263int roar_stream_add_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
264 struct roar_message m;
265
266 m.cmd     = ROAR_CMD_ADD_DATA;
267 m.stream  = s->id;
268 m.pos     = 0;
269 m.datalen = len;
270
271// if ( roar_req(con, &m, (void**)&data) == -1 )
272//  return -1;
273 if ( roar_send_message(con, &m, data) != 0 )
274  return -1;
275
276 if ( roar_recv_message(con, &m, NULL) == -1 )
277  return -1;
278
279 if ( m.cmd == ROAR_CMD_OK )
280  return 0;
281 return -1;
282}
283
284int roar_stream_send_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
285 if ( ! s )
286  return -1;
287
288 if ( s->fh == -1 ) {
289  if ( !con )
290   return -1;
291
292  if ( roar_stream_add_data(con, s, data, len) == -1 )
293   return -1;
294
295  return len;
296 }
297
298 return write(s->fh, data, len);
299}
300
301int roar_stream_get_info (struct roar_connection * con, struct roar_stream * s, struct roar_stream_info * info) {
302 struct roar_message m;
303 uint16_t * data = (uint16_t *) m.data;
304 int i;
305
306 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
307 m.stream  = s->id;
308 m.datalen = 4;
309 m.pos     = 0;
310
311 data[0] = 0; // Version and reserved
312 data[1] = 1; // stream
313
314 for (i = 0; i < m.datalen/2; i++) {
315  data[i] = ROAR_HOST2NET16(data[i]);
316 }
317
318 if ( roar_req(con, &m, NULL) == -1 )
319  return -1;
320
321 if ( m.cmd != ROAR_CMD_OK )
322  return -1;
323
324 for (i = 0; i < m.datalen/2; i++) {
325  data[i] = ROAR_NET2HOST16(data[i]);
326 }
327
328 if ( m.datalen < 7*2 )
329  return -1;
330
331 if ( data[0] != 0 || data[1] != 1 )
332  return -1;
333
334 memset(info, 0, sizeof(struct roar_stream_info));
335
336 info->block_size     = data[2];
337 info->pre_underruns  = data[3];
338 info->post_underruns = data[4];
339 info->codec          = data[5];
340 info->flags          = data[6];
341 info->delay          = data[7]*1000;
342
343 return 0;
344}
345
346int roar_stream_set_flags (struct roar_connection * con, struct roar_stream * s, int flags, int reset) {
347 struct roar_message m;
348 uint16_t * data = (uint16_t *) m.data;
349 int i;
350
351 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
352 m.stream  = s->id;
353 m.datalen = 8;
354 m.pos     = 0;
355
356 data[0] = 0; // Version and reserved
357 data[1] = 2; // flags
358 data[2] = reset == ROAR_RESET_FLAG ? ROAR_RESET_FLAG : ROAR_SET_FLAG;
359 data[3] = flags;
360
361 for (i = 0; i < m.datalen/2; i++) {
362  data[i] = ROAR_HOST2NET16(data[i]);
363 }
364
365 if ( roar_req(con, &m, NULL) == -1 )
366  return -1;
367
368 if ( m.cmd != ROAR_CMD_OK )
369  return -1;
370
371 return 0;
372}
373
374#define _ROAR_STREAM_MESSAGE_LEN ((5+1)*4)
375
376int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m) {
377 uint32_t * data;
378 int i;
379
380 if ( !(s && m) )
381  return -1;
382
383 m->datalen = _ROAR_STREAM_MESSAGE_LEN;
384 data = (uint32_t*) m->data;
385
386 data[0] = s->dir;
387 data[1] = s->pos_rel_id;
388 data[2] = s->info.rate;
389 data[3] = s->info.bits;
390 data[4] = s->info.channels;
391 data[5] = s->info.codec;
392
393 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
394  data[i] = ROAR_HOST2NET32(data[i]);
395
396 ROAR_DBG("roar_stream_s2m(*): s->info:");
397 roar_debug_audio_info_print(&s->info);
398
399 m->pos = s->pos;
400
401 return 0;
402}
403int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m) {
404 uint32_t * data;
405 int i;
406
407 if ( !(s && m) )
408  return -1;
409
410 if ( m->datalen != _ROAR_STREAM_MESSAGE_LEN )
411  return -1;
412
413 s->pos = m->pos;
414
415 data = (uint32_t*) m->data;
416
417 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
418  data[i] = ROAR_NET2HOST32(data[i]);
419
420 s->id            = m->stream;
421 s->dir           = data[0];
422 s->pos_rel_id    = data[1];
423 s->info.rate     = data[2];
424 s->info.bits     = data[3];
425 s->info.channels = data[4];
426 s->info.codec    = data[5];
427
428 ROAR_DBG("roar_stream_m2s(*): s->info:");
429 roar_debug_audio_info_print(&s->info);
430
431 return 0;
432}
433
434
435// codec funcs:
436
437/*
438#define roar_codec2str(x) ((x) == ROAR_CODEC_PCM_S_LE  ? "pcm_s_le"  : (x) == ROAR_CODEC_PCM_S_BE  ? "pcm_s_be"  : \
439                           (x) == ROAR_CODEC_PCM_S_PDP ? "pcm_s_pdp" : (x) == ROAR_CODEC_MIDI_FILE ? "midi_file" : \
440                           "unknown" )
441*/
442
443struct {
444 int    codec;
445 char * name;
446} _libroar_codec[] = {
447 // PCM:
448 {ROAR_CODEC_PCM_S_LE,    "pcm_s_le"   },
449 {ROAR_CODEC_PCM_S_BE,    "pcm_s_be"   },
450 {ROAR_CODEC_PCM_S_PDP,   "pcm_s_pdp"  },
451 {ROAR_CODEC_PCM_U_LE,    "pcm_u_le"   },
452 {ROAR_CODEC_PCM_U_BE,    "pcm_u_be"   },
453 {ROAR_CODEC_PCM_U_PDP,   "pcm_u_pdp"  },
454 {ROAR_CODEC_DEFAULT,     "default"    }, // alias
455 {ROAR_CODEC_DEFAULT,     "pcm"        }, // alias
456 {ROAR_CODEC_DEFAULT,     "raw"        }, // alias
457
458 // MIDI:
459 {ROAR_CODEC_MIDI_FILE,   "midi_file"  },
460
461 // XIPH:
462 {ROAR_CODEC_OGG_VORBIS,  "ogg_vorbis" },
463 {ROAR_CODEC_OGG_VORBIS,  "vorbis"     }, // alias
464 {ROAR_CODEC_FLAC,        "flac"       },
465 {ROAR_CODEC_OGG_SPEEX,   "ogg_speex"  },
466 {ROAR_CODEC_OGG_SPEEX,   "speex"      }, // alias
467 {ROAR_CODEC_OGG_FLAC,    "ogg_flac"   },
468 {ROAR_CODEC_OGG_GENERAL, "ogg_general"},
469 {ROAR_CODEC_ROAR_CELT,   "roar_celt"  },
470 {ROAR_CODEC_ROAR_SPEEX,  "roar_speex" },
471
472 // RAUM:
473 {ROAR_CODEC_RAUM,        "raum"       },
474 {ROAR_CODEC_RAUM_VORBIS, "raum_vorbis"},
475
476 // RIFF/WAVE like:
477 {ROAR_CODEC_RIFF_WAVE,   "riff_wave"  },
478 {ROAR_CODEC_RIFF_WAVE,   "wave"       }, // alias
479 {ROAR_CODEC_RIFF_WAVE,   "wav"        }, // alias
480
481 //Log codecs:
482 {ROAR_CODEC_ALAW,        "alaw"       },
483 {ROAR_CODEC_MULAW,       "mulaw"      },
484 {ROAR_CODEC_MULAW,       "ulaw"       }, // alias
485
486 // Meta Codecs:
487 {ROAR_CODEC_META_VCLT,     "meta_vclt"    },
488 {ROAR_CODEC_META_RALT,     "meta_ralt"    },
489 {ROAR_CODEC_META_RALB,     "meta_ralb"    },
490 {ROAR_CODEC_META_RALB_LE,  "meta_ralb_le" },
491 {ROAR_CODEC_META_RALB_BE,  "meta_ralb_be" },
492 {ROAR_CODEC_META_RALB_PDP, "meta_ralb_pdp"},
493
494 {-1, NULL}
495};
496
497int roar_str2codec(char * codec) {
498 int i;
499 int guess;
500
501 if ( codec == NULL || *codec == 0 )
502  return ROAR_CODEC_DEFAULT;
503
504 if ( (guess = atoi(codec)) > 0 )
505  return guess;
506
507 if ( codec == NULL || *codec == 0 )
508  return ROAR_CODEC_DEFAULT;
509
510 for (i = 0; _libroar_codec[i].codec != -1; i++)
511  if ( strcasecmp(_libroar_codec[i].name, codec) == 0 )
512   return _libroar_codec[i].codec;
513
514 return -1;
515}
516
517
518char * roar_codec2str (int codec) {
519 int i;
520
521 for (i = 0; _libroar_codec[i].codec != -1; i++)
522  if ( _libroar_codec[i].codec == codec )
523   return _libroar_codec[i].name;
524
525 return "unknown";
526}
527
528//ll
Note: See TracBrowser for help on using the repository browser.