source: roaraudio/libroar/stream.c @ 1842:8c8a003773ca

Last change on this file since 1842:8c8a003773ca was 1842:8c8a003773ca, checked in by phi, 15 years ago

support for names on server streams, added roar_stream_get_name()

File size: 14.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 if ( s == NULL )
67  return -1;
68
69 s->fh         = -1;
70 s->id         = -1;
71 s->pos        =  0;
72 s->pos_rel_id = -1;
73
74 s->dir        = ROAR_DIR_DEFAULT;
75
76/*
77 s->datalen    = 0;
78 s->offset     = 0;
79
80 s->database   = NULL;
81 s->dataoff    = NULL;
82*/
83
84 s->info.rate     = rate;
85 s->info.channels = channels;
86 s->info.bits     = bits;
87 s->info.codec    = codec;
88
89 if ( bits > ROAR_BITS_MAX )
90  return -1;
91
92 return 0;
93}
94
95int roar_stream_set_rel_id(struct roar_stream * s, int id) {
96 if ( s == NULL )
97  return -1;
98
99 s->pos_rel_id = id;
100
101 return 0;
102}
103
104int roar_stream_get_rel_id(struct roar_stream * s) {
105 if ( s == NULL )
106  return -1;
107
108 return s->pos_rel_id;
109}
110
111int roar_stream_new_by_id(struct roar_stream * s, int id) {
112 if ( s == NULL )
113  return -1;
114
115 if ( roar_stream_new_empty(s) == -1 )
116  return -1;
117
118 return roar_stream_set_id(s, id);
119}
120
121int roar_stream_new_empty(struct roar_stream * s) {
122 if ( s == NULL )
123  return -1;
124
125 return roar_stream_new(s, 0, 0, 0, 0);
126}
127
128int roar_stream_set_id (struct roar_stream * s, int id) {
129 if ( s == NULL )
130  return -1;
131
132 s->id = id;
133
134 return 0;
135}
136
137int roar_stream_get_id (struct roar_stream * s) {
138 if ( s == NULL )
139  return -1;
140
141 return s->id;
142}
143
144int roar_stream_set_fh (struct roar_stream * s, int fh) {
145 if ( s == NULL )
146  return -1;
147
148 s->fh = fh;
149
150 return 0;
151}
152
153int roar_stream_get_fh (struct roar_stream * s) {
154 if ( s == NULL )
155  return -1;
156
157 return s->fh;
158}
159
160
161int roar_stream_exec    (struct roar_connection * con, struct roar_stream * s) {
162 struct roar_message m;
163
164 m.cmd     = ROAR_CMD_EXEC_STREAM;
165 m.stream  = s->id;
166 m.datalen = 0;
167 m.pos     = 0;
168
169 if ( roar_req(con, &m, NULL) == -1 )
170  return -1;
171
172 if ( m.cmd == ROAR_CMD_OK )
173  return 0;
174 return -1;
175}
176
177int roar_stream_connect_to (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
178 struct roar_message m;
179
180 if ( roar_stream_connect_to_ask(con, s, type, host, port) == -1 )
181  return -1;
182
183 if ( roar_recv_message(con, &m, NULL) == -1 )
184  return -1;
185
186 if ( m.cmd == ROAR_CMD_OK )
187  return 0;
188 return -1;
189}
190
191int roar_stream_connect_to_ask (struct roar_connection * con, struct roar_stream * s, int type, char * host, int port) {
192 struct roar_message m;
193 int len = 0;
194
195 if ( host == NULL )
196  return -1;
197
198 ROAR_DBG("roar_stream_connect_to_ask(*): Ask the server to connect to: %s:%i", host, port);
199
200 m.cmd     = ROAR_CMD_CON_STREAM;
201 m.stream  = s->id;
202 m.pos     = 0;
203
204 m.data[0] = 0;
205 m.data[1] = type;
206 ((uint16_t*)&(m.data))[1] = ROAR_HOST2NET16(port);
207
208 len = strlen(host);
209
210 if ( len > 76 )
211  return -1;
212
213 strncpy(&(m.data[4]), host, len);
214
215 m.datalen = len + 4;
216
217 if ( roar_send_message(con, &m, NULL) == -1 )
218  return -1;
219
220 return 0;
221}
222
223int roar_stream_passfh  (struct roar_connection * con, struct roar_stream * s, int fh) {
224 struct roar_message m;
225 int confh;
226
227 m.cmd     = ROAR_CMD_PASSFH;
228 m.stream  = s->id;
229 m.pos     = 0;
230 m.datalen = 0;
231
232 ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = ?", con->fh, s->id, fh);
233
234 if ( (confh = roar_get_connection_fh(con)) == -1 )
235  return -1;
236
237 if ( roar_send_message(con, &m, NULL) == -1 ) {
238  ROAR_DBG("roar_stream_passfh(con={.fh=%i,...}, s={.id=%i,...}, fh=%i) = -1 // can not send message", con->fh, s->id, fh);
239  return -1;
240 }
241
242 ROAR_DBG("roar_stream_passfh(*): msg send");
243
244 if ( roar_socket_send_fh(confh, fh, NULL, 0) == -1 )
245  return -1;
246
247 ROAR_DBG("roar_stream_passfh(*): fh send");
248
249 if ( roar_recv_message(con, &m, NULL) == -1 )
250  return -1;
251
252 ROAR_DBG("roar_stream_passfh(*): mes recved");
253
254 if ( m.cmd == ROAR_CMD_OK )
255  return 0;
256
257 return -1;
258}
259
260int roar_stream_attach_simple (struct roar_connection * con, struct roar_stream * s, int client) {
261 struct roar_message m;
262 uint16_t * info = (uint16_t *) m.data;
263 int i;
264
265 m.cmd     = ROAR_CMD_ATTACH;
266 m.stream  = s->id;
267 m.pos     = 0;
268 m.datalen = 6;
269
270 info[0] = 0;
271 info[1] = ROAR_ATTACH_SIMPLE;
272 info[2] = client;
273
274 for (i = 0; i < m.datalen/2; i++) {
275  info[i] = ROAR_HOST2NET16(info[i]);
276 }
277
278 if ( roar_req(con, &m, NULL) == -1 )
279  return -1;
280
281 if ( m.cmd != ROAR_CMD_OK )
282  return -1;
283
284 return 0;
285}
286
287int roar_stream_add_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
288 struct roar_message m;
289
290 m.cmd     = ROAR_CMD_ADD_DATA;
291 m.stream  = s->id;
292 m.pos     = 0;
293 m.datalen = len;
294
295// if ( roar_req(con, &m, (void**)&data) == -1 )
296//  return -1;
297 if ( roar_send_message(con, &m, data) != 0 )
298  return -1;
299
300 if ( roar_recv_message(con, &m, NULL) == -1 )
301  return -1;
302
303 if ( m.cmd == ROAR_CMD_OK )
304  return 0;
305 return -1;
306}
307
308int roar_stream_send_data (struct roar_connection * con, struct roar_stream * s, char * data, size_t len) {
309 if ( ! s )
310  return -1;
311
312 if ( s->fh == -1 ) {
313  if ( !con )
314   return -1;
315
316  if ( roar_stream_add_data(con, s, data, len) == -1 )
317   return -1;
318
319  return len;
320 }
321
322#ifdef ROAR_HAVE_IO_POSIX
323 return write(s->fh, data, len);
324#endif
325
326 return -1;
327}
328
329int roar_stream_get_info (struct roar_connection * con, struct roar_stream * s, struct roar_stream_info * info) {
330 struct roar_message m;
331 uint16_t * data = (uint16_t *) m.data;
332 int i;
333
334 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
335 m.stream  = s->id;
336 m.datalen = 4;
337 m.pos     = 0;
338
339 data[0] = 0; // Version and reserved
340 data[1] = ROAR_STREAM_PARA_INFO; // stream
341
342 for (i = 0; i < m.datalen/2; i++) {
343  data[i] = ROAR_HOST2NET16(data[i]);
344 }
345
346 if ( roar_req(con, &m, NULL) == -1 )
347  return -1;
348
349 if ( m.cmd != ROAR_CMD_OK )
350  return -1;
351
352 for (i = 0; i < m.datalen/2; i++) {
353  data[i] = ROAR_NET2HOST16(data[i]);
354 }
355
356 if ( m.datalen < 7*2 )
357  return -1;
358
359 if ( data[0] != 0 || data[1] != 1 )
360  return -1;
361
362 memset(info, 0, sizeof(struct roar_stream_info));
363
364 info->block_size     = data[2];
365 info->pre_underruns  = data[3];
366 info->post_underruns = data[4];
367 info->codec          = data[5];
368 info->flags          = data[6];
369 info->delay          = data[7]*1000;
370
371 return 0;
372}
373
374int roar_stream_get_name (struct roar_connection * con, struct roar_stream * s, char * name, size_t len) {
375 struct roar_message m;
376 uint16_t * data = (uint16_t *) m.data;
377
378 if ( con == NULL || s == NULL || name == NULL || len == 0 )
379  return -1;
380
381 name[0] = 0; // just in case...
382
383 m.cmd     = ROAR_CMD_GET_STREAM_PARA;
384 m.stream  = s->id;
385 m.datalen = 4;
386 m.pos     = 0;
387
388 data[0] = 0; // Version and reserved
389 data[1] = ROAR_STREAM_PARA_NAME; // stream
390
391 data[0] = ROAR_HOST2NET16(data[0]);
392 data[1] = ROAR_HOST2NET16(data[1]);
393
394 ROAR_DBG("roar_stream_get_name(*) = ?");
395
396 if ( roar_req(con, &m, NULL) == -1 )
397  return -1;
398
399 ROAR_DBG("roar_stream_get_name(*) = ?");
400
401 if ( m.cmd != ROAR_CMD_OK )
402  return -1;
403
404 ROAR_DBG("roar_stream_get_name(*) = ?");
405
406 if ( m.datalen < 4 )
407  return -1;
408
409 data[0] = ROAR_NET2HOST16(data[0]);
410 data[1] = ROAR_NET2HOST16(data[1]);
411
412 ROAR_DBG("roar_stream_get_name(*) = ?");
413
414 if ( data[0] != 0 || data[1] != ROAR_STREAM_PARA_NAME )
415  return -1;
416
417 m.datalen -= 4;
418
419 len--;
420
421 if ( len > m.datalen )
422  len = m.datalen;
423
424 strncpy(name, ((char*)m.data)+4, len);
425 name[len] = 0;
426
427 ROAR_DBG("roar_stream_get_name(*) = 0");
428
429 return 0;
430}
431
432int roar_stream_set_flags (struct roar_connection * con, struct roar_stream * s, int flags, int reset) {
433 struct roar_message m;
434 uint16_t * data = (uint16_t *) m.data;
435 int i;
436
437 m.cmd     = ROAR_CMD_SET_STREAM_PARA;
438 m.stream  = s->id;
439 m.datalen = 8;
440 m.pos     = 0;
441
442 data[0] = 0; // Version and reserved
443 data[1] = 2; // flags
444 data[2] = reset == ROAR_RESET_FLAG ? ROAR_RESET_FLAG : ROAR_SET_FLAG;
445 data[3] = flags;
446
447 for (i = 0; i < m.datalen/2; i++) {
448  data[i] = ROAR_HOST2NET16(data[i]);
449 }
450
451 if ( roar_req(con, &m, NULL) == -1 )
452  return -1;
453
454 if ( m.cmd != ROAR_CMD_OK )
455  return -1;
456
457 return 0;
458}
459
460#define _ROAR_STREAM_MESSAGE_LEN ((5+1)*4)
461
462int roar_stream_s2m     (struct roar_stream * s, struct roar_message * m) {
463 uint32_t * data;
464 int i;
465
466 if ( !(s && m) )
467  return -1;
468
469 m->datalen = _ROAR_STREAM_MESSAGE_LEN;
470 data = (uint32_t*) m->data;
471
472 data[0] = s->dir;
473 data[1] = s->pos_rel_id;
474 data[2] = s->info.rate;
475 data[3] = s->info.bits;
476 data[4] = s->info.channels;
477 data[5] = s->info.codec;
478
479 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
480  data[i] = ROAR_HOST2NET32(data[i]);
481
482 ROAR_DBG("roar_stream_s2m(*): s->info:");
483 roar_debug_audio_info_print(&s->info);
484
485 m->pos = s->pos;
486
487 return 0;
488}
489int roar_stream_m2s     (struct roar_stream * s, struct roar_message * m) {
490 uint32_t * data;
491 int i;
492
493 if ( !(s && m) )
494  return -1;
495
496 if ( m->datalen != _ROAR_STREAM_MESSAGE_LEN )
497  return -1;
498
499 s->pos = m->pos;
500
501 data = (uint32_t*) m->data;
502
503 for (i = 0; i < _ROAR_STREAM_MESSAGE_LEN/4; i++)
504  data[i] = ROAR_NET2HOST32(data[i]);
505
506 s->id            = m->stream;
507 s->dir           = data[0];
508 s->pos_rel_id    = data[1];
509 s->info.rate     = data[2];
510 s->info.bits     = data[3];
511 s->info.channels = data[4];
512 s->info.codec    = data[5];
513
514 ROAR_DBG("roar_stream_m2s(*): s->info:");
515 roar_debug_audio_info_print(&s->info);
516
517 return 0;
518}
519
520// stream direction funcs:
521/*
522#define roar_dir2str(x)   ((x) == ROAR_DIR_PLAY   ? "play"   : (x) == ROAR_DIR_MONITOR ? "monitor" : \
523                           (x) == ROAR_DIR_FILTER ? "filter" : (x) == ROAR_DIR_RECORD  ? "record"  : \
524                           (x) == ROAR_DIR_OUTPUT ? "output" : (x) == ROAR_DIR_BIDIR   ? "bidir"   : \
525                           (x) == ROAR_DIR_MIXING ? "mixing" : \
526                           "unknown")
527*/
528
529char * roar_dir2str (int dir) {
530 switch (dir) {
531  case ROAR_DIR_PLAY:
532    return "play";
533   break;
534  case ROAR_DIR_RECORD:
535    return "record";
536   break;
537  case ROAR_DIR_MONITOR:
538    return "monitor";
539   break;
540  case ROAR_DIR_FILTER:
541    return "filter";
542   break;
543  case ROAR_DIR_OUTPUT:
544    return "output";
545   break;
546  case ROAR_DIR_MIXING:
547    return "mixing";
548   break;
549  case ROAR_DIR_META:
550    return "meta";
551   break;
552  case ROAR_DIR_BIDIR:
553    return "bidir";
554   break;
555  case ROAR_DIR_THRU:
556    return "thru";
557   break;
558  case ROAR_DIR_BRIDGE:
559    return "bridge";
560   break;
561  case ROAR_DIR_MIDI_IN:
562    return "midi_in";
563   break;
564  case ROAR_DIR_MIDI_OUT:
565    return "midi_out";
566   break;
567  case ROAR_DIR_LIGHT_IN:
568    return "light_in";
569   break;
570  case ROAR_DIR_LIGHT_OUT:
571    return "light_out";
572   break;
573  default:
574    return "unknown";
575 }
576}
577
578// codec funcs:
579
580/*
581#define roar_codec2str(x) ((x) == ROAR_CODEC_PCM_S_LE  ? "pcm_s_le"  : (x) == ROAR_CODEC_PCM_S_BE  ? "pcm_s_be"  : \
582                           (x) == ROAR_CODEC_PCM_S_PDP ? "pcm_s_pdp" : (x) == ROAR_CODEC_MIDI_FILE ? "midi_file" : \
583                           "unknown" )
584*/
585
586struct {
587 int    codec;
588 char * name;
589} _libroar_codec[] = {
590 // PCM:
591 {ROAR_CODEC_PCM_S_LE,    "pcm_s_le"   },
592 {ROAR_CODEC_PCM_S_BE,    "pcm_s_be"   },
593 {ROAR_CODEC_PCM_S_PDP,   "pcm_s_pdp"  },
594 {ROAR_CODEC_PCM_U_LE,    "pcm_u_le"   },
595 {ROAR_CODEC_PCM_U_BE,    "pcm_u_be"   },
596 {ROAR_CODEC_PCM_U_PDP,   "pcm_u_pdp"  },
597 {ROAR_CODEC_DEFAULT,     "default"    }, // alias
598 {ROAR_CODEC_DEFAULT,     "pcm"        }, // alias
599 {ROAR_CODEC_DEFAULT,     "raw"        }, // alias
600
601 // MIDI:
602 {ROAR_CODEC_MIDI_FILE,   "midi_file"  },
603 {ROAR_CODEC_MIDI,        "midi"       },
604
605 // XIPH:
606 {ROAR_CODEC_OGG_VORBIS,  "ogg_vorbis" },
607 {ROAR_CODEC_OGG_VORBIS,  "vorbis"     }, // alias
608 {ROAR_CODEC_FLAC,        "flac"       },
609 {ROAR_CODEC_OGG_SPEEX,   "ogg_speex"  },
610 {ROAR_CODEC_OGG_SPEEX,   "speex"      }, // alias
611 {ROAR_CODEC_OGG_FLAC,    "ogg_flac"   },
612 {ROAR_CODEC_OGG_GENERAL, "ogg_general"},
613 {ROAR_CODEC_ROAR_CELT,   "roar_celt"  },
614 {ROAR_CODEC_ROAR_SPEEX,  "roar_speex" },
615
616 // RAUM:
617 {ROAR_CODEC_RAUM,        "raum"       },
618 {ROAR_CODEC_RAUM_VORBIS, "raum_vorbis"},
619
620 // RIFF/WAVE like:
621 {ROAR_CODEC_RIFF_WAVE,   "riff_wave"  },
622 {ROAR_CODEC_RIFF_WAVE,   "wave"       }, // alias
623 {ROAR_CODEC_RIFF_WAVE,   "wav"        }, // alias
624
625 //Log codecs:
626 {ROAR_CODEC_ALAW,        "alaw"       },
627 {ROAR_CODEC_MULAW,       "mulaw"      },
628 {ROAR_CODEC_MULAW,       "ulaw"       }, // alias
629
630 // Meta Codecs:
631 {ROAR_CODEC_META_VCLT,     "meta_vclt"    },
632 {ROAR_CODEC_META_RALT,     "meta_ralt"    },
633 {ROAR_CODEC_META_RALB,     "meta_ralb"    },
634 {ROAR_CODEC_META_RALB_LE,  "meta_ralb_le" },
635 {ROAR_CODEC_META_RALB_BE,  "meta_ralb_be" },
636 {ROAR_CODEC_META_RALB_PDP, "meta_ralb_pdp"},
637
638 // light control:
639 {ROAR_CODEC_DMX512,      "dmx512"     },
640
641 {-1, NULL}
642};
643
644int roar_str2codec(char * codec) {
645 int i;
646 int guess;
647
648 if ( codec == NULL || *codec == 0 )
649  return ROAR_CODEC_DEFAULT;
650
651 if ( (guess = atoi(codec)) > 0 )
652  return guess;
653
654 if ( codec == NULL || *codec == 0 )
655  return ROAR_CODEC_DEFAULT;
656
657 for (i = 0; _libroar_codec[i].codec != -1; i++)
658  if ( strcasecmp(_libroar_codec[i].name, codec) == 0 )
659   return _libroar_codec[i].codec;
660
661 return -1;
662}
663
664
665char * roar_codec2str (int codec) {
666 int i;
667
668 for (i = 0; _libroar_codec[i].codec != -1; i++)
669  if ( _libroar_codec[i].codec == codec )
670   return _libroar_codec[i].name;
671
672 return "unknown";
673}
674
675//ll
Note: See TracBrowser for help on using the repository browser.